private static Collection<String> suggestKeywords(PsiElement position) { TextRange posRange = position.getTextRange(); BnfFile posFile = (BnfFile) position.getContainingFile(); BnfRule statement = PsiTreeUtil.getTopmostParentOfType(position, BnfRule.class); final TextRange range; if (statement != null) { range = new TextRange(statement.getTextRange().getStartOffset(), posRange.getStartOffset()); } else { int offset = posRange.getStartOffset(); for (PsiElement cur = GrammarUtil.getDummyAwarePrevSibling(position); cur != null; cur = GrammarUtil.getDummyAwarePrevSibling(cur)) { if (cur instanceof BnfAttrs) offset = cur.getTextRange().getEndOffset(); else if (cur instanceof BnfRule) offset = cur.getTextRange().getStartOffset(); else continue; break; } range = new TextRange(offset, posRange.getStartOffset()); } final String text = range.isEmpty() ? CompletionInitializationContext.DUMMY_IDENTIFIER : range.substring(posFile.getText()); PsiFile file = PsiFileFactory.getInstance(posFile.getProject()) .createFileFromText("a.bnf", BnfLanguage.INSTANCE, text, true, false); int completionOffset = posRange.getStartOffset() - range.getStartOffset(); GeneratedParserUtilBase.CompletionState state = new GeneratedParserUtilBase.CompletionState(completionOffset) { @Override public String convertItem(Object o) { // we do not have other keywords return o instanceof String ? (String) o : null; } }; file.putUserData(GeneratedParserUtilBase.COMPLETION_STATE_KEY, state); TreeUtil.ensureParsed(file.getNode()); return state.items; }
@Override public void inlineElement(Project project, Editor editor, PsiElement psiElement) { BnfRule rule = (BnfRule) psiElement; BnfAttrs attrs = rule.getAttrs(); if (PsiTreeUtil.hasErrorElements(rule)) { CommonRefactoringUtil.showErrorHint(project, editor, "Rule has errors", "Inline Rule", null); return; } if (attrs != null && !attrs.getAttrList().isEmpty()) { CommonRefactoringUtil.showErrorHint( project, editor, "Rule has attributes", "Inline Rule", null); return; } Collection<PsiReference> allReferences = ReferencesSearch.search(psiElement).findAll(); if (allReferences.isEmpty()) { CommonRefactoringUtil.showErrorHint( project, editor, "Rule is never used", "Inline Rule", null); return; } boolean hasNonAttributeRefs = false; for (PsiReference ref : allReferences) { if (!GrammarUtil.isInAttributesReference(ref.getElement())) { hasNonAttributeRefs = true; break; } } if (!hasNonAttributeRefs) { CommonRefactoringUtil.showErrorHint( project, editor, "Rule is referenced only in attributes", "Inline Rule", null); return; } if (!CommonRefactoringUtil.checkReadOnlyStatus(project, rule)) return; PsiReference reference = editor != null ? TargetElementUtilBase.findReference(editor, editor.getCaretModel().getOffset()) : null; if (reference != null && !rule.equals(reference.resolve())) { reference = null; } InlineRuleDialog dialog = new InlineRuleDialog(project, rule, reference); dialog.show(); }