/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright (c) 2015-2015 Vladimir Schneider <vladimir.schneider@gmail.com>
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* This file is based on the IntelliJ SimplePlugin tutorial
*
*/
package com.vladsch.idea.multimarkdown.language;
import com.intellij.psi.PsiElement;
import com.intellij.psi.codeStyle.SuggestedNameInfo;
import com.intellij.refactoring.rename.PreferrableNameSuggestionProvider;
import com.intellij.util.containers.ContainerUtil;
import com.vladsch.idea.multimarkdown.psi.*;
import com.vladsch.idea.multimarkdown.spellchecking.MultiMarkdownIdentifierTokenizer;
import com.vladsch.idea.multimarkdown.spellchecking.Suggestion;
import com.vladsch.idea.multimarkdown.spellchecking.SuggestionList;
import com.vladsch.idea.multimarkdown.util.*;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.Set;
import static com.vladsch.idea.multimarkdown.spellchecking.SuggestionFixers.*;
public class ElementNameSuggestionProvider extends PreferrableNameSuggestionProvider {
private boolean active;
private boolean selfActivated;
public void setActive(boolean active) {
this.active = active;
if (!active) selfActivated = false;
}
@Override
public boolean shouldCheckOthers() {
return !(active || selfActivated);
}
@Override
public SuggestedNameInfo getSuggestedNames(PsiElement element, PsiElement nameSuggestionContext, Set<String> result) {
assert result != null;
selfActivated = false;
SuggestedNameInfo suggestedNameInfo = null;
if (nameSuggestionContext == null || !(element instanceof MultiMarkdownFile || element instanceof MultiMarkdownNamedElement)) {
return null;
}
selfActivated = !active;
active = true;
if (element instanceof MultiMarkdownFile) {
//noinspection ConstantConditions
// this is a rename of a file on a link ref pointing to a valid file
SuggestionList suggestionList = new SuggestionList(element.getProject());
PathInfo filePathInfo = new PathInfo(((MultiMarkdownFile) element).getVirtualFile().getPath());
suggestionList = suggestionList
.add(WikiLinkRef.fileAsLink(filePathInfo.getFileNameNoExt()), new Suggestion.Param<String>(Suggestion.Fixer.FILE_PATH, filePathInfo.getFilePath()))
.add(suggestionList.chainFixers(SuggestCleanSpacedWords, (!selfActivated ? SuggestSpelling : null)))
.batchFixers(
SuggestCleanSpacedWords, SuggestCapSpacedWords
//, SuggestCleanDashedWords, SuggestCapDashedWords
//, SuggestCleanSplicedWords, SuggestCapSplicedWords
)
// fix names to files from wiki refs and remove those that we cannot use
.chainFixers(SuggestWikiRefAsFilNameWithExt, SuggestRemoveInvalidFileNames);
if (suggestionList.size() > 0) {
ContainerUtil.addAllNotNull(result, suggestionList.asList());
suggestedNameInfo = SuggestedNameInfo.NULL_INFO;
}
return suggestedNameInfo;
} else if (element instanceof MultiMarkdownWikiLinkText) {
// this is a rename on a wiki page title
// always activate spelling suggestions for renaming wiki page refs
// Get suggestions from the name of the pageRef text
SuggestionList suggestionList = getLinkTextSuggestions(element.getParent(), !selfActivated);
if (suggestionList.size() > 0) {
ContainerUtil.addAllNotNull(result, suggestionList.asList());
suggestedNameInfo = SuggestedNameInfo.NULL_INFO;
}
return suggestedNameInfo;
} else if (element instanceof MultiMarkdownWikiLinkRef) {
// this is a rename on a missing link element, provide list of valid markdown files that can be reached via wikiPageRef
// always activate spelling suggestions for renaming wiki page refs
SuggestionList suggestionList = new SuggestionList(element.getProject());
FileRef fileRef = new FileRef(element.getContainingFile());
LinkRef linkRef = new WikiLinkRef(fileRef, "", null, null);
GitHubLinkResolver resolver = new GitHubLinkResolver(element.getContainingFile());
List<PathInfo> linkRefs = resolver.multiResolve(linkRef, LinkResolver.LOOSE_MATCH, null);
if (linkRefs.size() > 0) {
// add fixed up version to result
suggestionList.addAll(PathInfo.fileNamesNoExt(linkRefs));
}
if (suggestionList.size() > 0) {
ContainerUtil.addAllNotNull(result, suggestionList.asList());
suggestedNameInfo = SuggestedNameInfo.NULL_INFO;
}
return suggestedNameInfo;
} else {
// this is a rename on an element
// only activate spelling suggestions if spell check activated
if (!selfActivated) {
SuggestionList uncheckedSuggestionList = new SuggestionList(element.getProject());
final StringBuilder text = new StringBuilder(element.getTextLength());
MultiMarkdownIdentifierTokenizer tokenizer = new MultiMarkdownIdentifierTokenizer();
Suggestion.Param<Boolean> param = new Suggestion.Param<Boolean>(Suggestion.Fixer.NEEDS_SPELLING_FIXER, true);
tokenizer.tokenizeSpellingSuggestions((MultiMarkdownNamedElement) element, new MultiMarkdownIdentifierTokenizer.SpellCheckConsumer() {
@Override
public void consume(String word, boolean spellCheck) {
text.append(word);
}
});
uncheckedSuggestionList.add(text.toString(), param);
SuggestionList suggestionList = uncheckedSuggestionList.batchFixers(SuggestSpelling);
if (suggestionList.size() > 0) {
ContainerUtil.addAllNotNull(result, suggestionList.asList());
suggestedNameInfo = SuggestedNameInfo.NULL_INFO;
}
return suggestedNameInfo;
}
}
// false alarm, go back to sleep
selfActivated = false;
active = false;
return null;
}
@NotNull
public static SuggestionList getLinkTextSuggestions(@NotNull PsiElement parent, boolean spellCheck) {
SuggestionList suggestionList = new SuggestionList(parent.getProject());
if (!(parent instanceof MultiMarkdownLinkElement)) return suggestionList;
MultiMarkdownLinkElement linkElement = (MultiMarkdownLinkElement) parent;
SuggestionList originalList = new SuggestionList(parent.getProject());
String linkText = linkElement.getLinkText();
String linkRefText = linkElement.getLinkRef();
String linkAnchor = linkElement.getLinkAnchor();
String originalText = null;
if (!linkText.isEmpty()) {
String text = linkText;
text = text.replace(MultiMarkdownCompletionContributor.DUMMY_IDENTIFIER, "").trim();
if (!text.isEmpty()) {
originalText = text;
originalList.add(text);
suggestionList.add(originalList);
}
}
if (!linkRefText.isEmpty()) {
String linkRef = new PathInfo(linkRefText).getFileNameNoExt();
if (!linkAnchor.isEmpty()) {
originalList.add(linkRef);
originalList.add(linkRef + ": " + linkAnchor);
SuggestionList anchoredList = new SuggestionList(originalList.getProject()).add(linkRef);
SuggestionList anchorList = new SuggestionList(originalList.getProject()).add(linkAnchor);
anchoredList.add(anchoredList.sequenceFixers(SuggestCleanSpacedWords, SuggestCapSpacedWords));
anchorList.add(anchorList.sequenceFixers(SuggestCleanSpacedWords, SuggestCapSpacedWords));
SuggestionList suggestions = new SuggestionList(originalList.getProject()).add(": ");
suggestions = suggestions.wrapPermuteFixedAligned(anchoredList, anchorList, SuggestCleanSpacedWords, SuggestCapSpacedWords);
originalList.add(suggestions);
}
suggestionList.add(linkRef);
String text = linkRef + " " + linkAnchor;
suggestionList.add(text);
// add with path parts that are in the link
linkRefText = new PathInfo(linkRefText).getPath();
suggestionList.add(linkRefText);
linkRefText = new PathInfo(linkRefText).getPath();
suggestionList.add(linkRefText + " " + text);
}
suggestionList = originalList.add(suggestionList.chainFixers(SuggestCleanSpacedWords, spellCheck ? SuggestSpelling : null)
, suggestionList.sequenceFixers(
SuggestCleanSpacedWords, SuggestCapSpacedWords, SuggestLowerSpacedWords
//, SuggestCleanDashedWords, SuggestCapDashedWords
//, SuggestCleanSplicedWords, SuggestCapSplicedWords
)
);
return suggestionList.size() == 1 && suggestionList.get(0).equals(originalText) ? SuggestionList.EMPTY_LIST : suggestionList;
}
}