use of org.eclipse.n4js.jsdoc.JSDocCharScanner.ScannerState in project n4js by eclipse.
the class JSDocCompletionProposalComputer method exec.
@SuppressWarnings("unchecked")
@Override
public ICompletionProposal[] exec(XtextResource xtextResource) throws Exception {
ContentAssistContext[] contexts = processor.getContextFactory().create(viewer, offset, xtextResource);
if (contexts.length > 0) {
ArrayList<ICompletionProposal> proposals = new ArrayList<>();
ContentAssistContext contentAssistContext = contexts[contexts.length - 1];
INode currentNode = contentAssistContext.getCurrentNode();
String content = currentNode.getText();
int offsetInNode = contentAssistContext.getOffset() - currentNode.getOffset() - contentAssistContext.getPrefix().length();
// String textInFront = content.substring(0, offsetInNode);
// System.out.println(textInFront);
N4JSDocletParser docletParser = processor.getDocletParser();
Doclet doclet = docletParser.parse(content);
Optional<String> lineTagPrefix = getLineTagTitlePrefix(content, offsetInNode);
if (lineTagPrefix.isPresent()) {
createLineTagProposal(lineTagPrefix.get(), docletParser, proposals);
}
Tag tag = JSDocletUtils.getTagAtOffset(doclet, offsetInNode);
if (tag != null) {
ITagDefinition tagDef = tag.getTagDefinition();
JSDocCharScanner scanner = new JSDocCharScanner(content);
ScannerState state = scanner.saveState();
scanner.setNextOffset(offsetInNode);
JSDocCompletionHint completionHint = tagDef.completionHint(scanner);
scanner.restoreState(state);
if (completionHint.kind != NOCOMPLETION) {
int replacementOffset = offset - completionHint.prefix.length();
if (completionHint.isTypeModelRef()) {
// get reference as far as it can be parsed:
FullMemberReference ref = completionHint.nodeAsFullMemberReference();
IContentAssistScopeProvider scopeProvider = (IContentAssistScopeProvider) processor.getScopeProvider();
IScope moduleSpecScope = scopeProvider.getScopeForContentAssist(// context for finding modules
xtextResource.getContents().get(0), N4JSPackage.Literals.IMPORT_DECLARATION__MODULE);
// complete module or type
if (!completionHint.isModuleNameCompleted()) {
for (IEObjectDescription moduleDescr : moduleSpecScope.getAllElements()) {
String moduleSpec = moduleDescr.getName().toString("/");
String moduleSimpleName = moduleDescr.getName().getLastSegment();
if (!moduleSpec.startsWith("#")) {
if (moduleSpec.startsWith(completionHint.prefix) || moduleSimpleName.startsWith(completionHint.prefix)) {
if (moduleSpec.length() == completionHint.prefix.length()) {
int replacementLength = 0;
int cursorPosition = 1;
ICompletionProposal proposal = new CompletionProposal(".", replacementOffset + completionHint.prefix.length(), replacementLength, cursorPosition);
proposals.add(proposal);
} else {
int replacementLength = completionHint.prefix.length();
int cursorPosition = moduleSpec.length();
ICompletionProposal proposal = new CompletionProposal(moduleSpec, replacementOffset, replacementLength, cursorPosition);
proposals.add(proposal);
}
}
}
}
} else {
QualifiedName moduleQN = QualifiedName.create(ref.getModuleName().split("/"));
IEObjectDescription descr = moduleSpecScope.getSingleElement(moduleQN);
if (descr != null && descr.getEObjectOrProxy() instanceof TModule) {
TModule module = (TModule) descr.getEObjectOrProxy();
if (module.eIsProxy())
module = (TModule) EcoreUtil.resolve(module, xtextResource);
if (!completionHint.isTypeNameCompleted(false) && completionHint.kind != MODULESPEC) {
String typePrefix = ref.getTypeName();
for (Type t : module.getTopLevelTypes()) {
String typeName = t.getName();
if (typeName.startsWith(typePrefix)) {
String completion = module.getModuleSpecifier() + "." + typeName;
int replacementLength = completionHint.prefix.length();
int cursorPosition = completion.length();
ICompletionProposal proposal = new CompletionProposal(completion, replacementOffset, replacementLength, cursorPosition);
proposals.add(proposal);
}
}
} else {
// completionHint.kind == MEMBER
Optional<Type> optType = module.getTopLevelTypes().stream().filter(t -> t.getName().equals(ref.getTypeName())).findAny();
if (optType.isPresent()) {
Type t = optType.get();
if (t instanceof ContainerType) {
String memberPrefix = ref.getMemberName();
for (TMember m : ((ContainerType<? extends TMember>) t).getOwnedMembers()) {
String memberName = m.getName();
if (memberName.startsWith(memberPrefix)) {
String completion = LineTagWithFullElementReference.createReferenceFromType(m).toString();
int replacementLength = completionHint.prefix.length();
int cursorPosition = completion.length();
ICompletionProposal proposal = new CompletionProposal(completion, replacementOffset, replacementLength, cursorPosition);
proposals.add(proposal);
}
}
}
}
}
}
}
}
}
}
ICompletionProposal[] result = new ICompletionProposal[proposals.size()];
proposals.toArray(result);
return result;
}
return null;
}
use of org.eclipse.n4js.jsdoc.JSDocCharScanner.ScannerState in project n4js by eclipse.
the class DescriptionParser method parseRegion.
/**
* Method used to parse Region encountered in text. Expects {@link JSDocCharScanner#nextNonWS()} to be beginning of
* region. It will use provided {@link TagDictionary} to recognize parse region. If no tags will mach parsed region,
* null is returned. If region is maching one of {@link InlineTag} definitions it will return result of parsing
* region with given tag.
*
* @param scanner
* JSDocCharScanner with offset_ before region
* @param inlineTagsDictinary
* Dictionary of tags used to parse given region
* @return Returns instance of Tag if parsed successfully, null otherwise.
*/
Tag parseRegion(JSDocCharScanner scanner, TagDictionary<AbstractInlineTagDefinition> inlineTagsDictinary) {
ScannerState stateBeforeRegion = scanner.saveState();
char _char = scanner.nextNonWS();
// unsafe if region is marked by more than one char
if (!regionStart(_char)) {
return null;
}
scanner.skipWS();
JSDocToken tokenTitle = TagTitleTokenizer.INSTANCE.nextToken(scanner);
if (tokenTitle != null) {
ITagDefinition iTagDefinition = inlineTagsDictinary.getDefinition(tokenTitle.token);
if (iTagDefinition != null) {
TagTitle tagTitle = createTagTitle(tokenTitle, iTagDefinition);
AbstractInlineTagDefinition tagDefinition = (AbstractInlineTagDefinition) iTagDefinition;
// although start of the region will be parsed twice (e.g. tag
// title) it allows given tag implementation to decide what to
// do with whole region, also might be important for nested
// regions detection.
scanner.restoreState(stateBeforeRegion);
InlineTag tag = (InlineTag) tagDefinition.parse(tagTitle, scanner);
tag.setRange(tokenTitle.start, scanner.offset());
return tag;
} else {
System.err.println("silent ignore of unrecognized InlineTag {" + tokenTitle.token + "}");
return null;
}
}
return null;
}
use of org.eclipse.n4js.jsdoc.JSDocCharScanner.ScannerState in project n4js by eclipse.
the class DescriptionParser method parse.
/**
* Returns Text if descriptions contains only text. If it contains any inline Tags, than returned composedContent
* will contain multiple nodes, one for each inline tag and one for each text before/after/in between inline tags.
* Order of data is preserved. Stops scanning for text when reaches end of comment or LineTag.
*
* InlineTags are identified based on dictionary provided with method call.
*/
public ContentNode parse(JSDocCharScanner scanner, TagDictionary<AbstractInlineTagDefinition> inlineTagsDictinary) {
ComposedContent description = DomFactory.eINSTANCE.createComposedContent();
if (!scanner.hasNext()) {
return null;
}
if (nextIsTagTitle(scanner)) {
return null;
}
int start = scanner.nextOffset();
int end = start;
StringBuilder strb = new StringBuilder();
while (scanner.hasNext()) {
char c = scanner.peek();
if (regionStart(c)) {
ScannerState st = scanner.saveState();
InlineTag tag = (InlineTag) parseRegion(scanner, inlineTagsDictinary);
if (tag != null) {
saveTextTokens(description, start, end, strb);
strb = new StringBuilder();
start = end;
description.getContents().add(tag);
continue;
} else {
scanner.restoreState(st);
if (start == end) {
assert false;
}
/*
* On unkown region just continue with text parsing
*/
// saveTextTokens(description, start, end, strb);
// break;
}
}
// consume c
scanner.next();
if (JSDocCharScanner.isNL(c)) {
if (scanner.hasNext() && !nextIsTagTitle(scanner)) {
end = scanner.offset();
} else {
break;
}
}
strb.append(c);
end = scanner.offset();
}
String pendingData = strb.toString();
if (pendingData.isEmpty() == false) {
saveTextTokens(description, start, end, strb);
}
switch(description.getContents().size()) {
case 0:
return null;
case 1:
return description.getContents().get(0);
default:
return description;
}
}
use of org.eclipse.n4js.jsdoc.JSDocCharScanner.ScannerState in project n4js by eclipse.
the class RegionTokenizer method findMarker.
private boolean findMarker(JSDocCharScanner scanner, final String marker) {
ScannerState state = scanner.saveState();
for (int i = 0; i < marker.length(); i++) {
if (!scanner.hasNext() || (i > 0 && scanner.skipped())) {
scanner.restoreState(state);
return false;
}
char expected = marker.charAt(i);
char ch = scanner.next();
if (expected != ch) {
scanner.restoreState(state);
return false;
}
}
return true;
}
Aggregations