/*
* Copyright 2013-2017 consulo.io
*
* Licensed 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.
*/
package com.intellij.codeInsight.hints.settings;
import com.intellij.lang.Language;
import com.intellij.openapi.components.*;
import com.intellij.openapi.util.JDOMUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashMap;
import org.jdom.Attribute;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
/**
* from kotlin
*/
@State(name = "ParameterNameHintsSettings", storages = {@Storage(file = StoragePathMacros.APP_CONFIG + "parameter.hints.xml")})
public class ParameterNameHintsSettings implements PersistentStateComponent<Element> {
private static final String BLACKLISTS = "blacklists";
private static final String LANGUAGE_LIST = "blacklist";
private static final String LANGUAGE = "language";
private static final String ADDED = "added";
private static final String REMOVED = "removed";
private static final String PATTERN = "pattern";
private static final String DO_NOT_SHOW_IF_PARAM_NAME_CONTAINED_IN_METHOD_NAME = "showIfParamNameContained";
private static final String SHOW_WHEN_MULTIPLE_PARAMS_WITH_SAME_TYPE = "showWhenMultipleParamsWithSameType";
@NotNull
public static ParameterNameHintsSettings getInstance() {
return ServiceManager.getService(ParameterNameHintsSettings.class);
}
private final Map<String, Set<String>> myRemovedPatterns = new HashMap<>();
private final Map<String, Set<String>> myAddedPatterns = new HashMap<>();
private boolean myIsDoNotShowIfMethodNameContainsParameterName = true;
private boolean myIsShowForParamsWithSameType = false;
public void addIgnorePattern(Language language, String pattern) {
Set<String> patternsBefore = getAddedPatterns(language);
setAddedPatterns(language, ContainerUtil.<String>newLinkedHashSet(patternsBefore, pattern));
}
public Diff getBlackListDiff(Language language) {
Set<String> added = getAddedPatterns(language);
Set<String> removed = getRemovedPatterns(language);
return new Diff(added, removed);
}
public void setBlackListDiff(Language language, Diff diff) {
setAddedPatterns(language, diff.getAdded());
setRemovedPatterns(language, diff.getRemoved());
}
public boolean isDoNotShowIfMethodNameContainsParameterName() {
return myIsDoNotShowIfMethodNameContainsParameterName;
}
public boolean isShowForParamsWithSameType() {
return myIsShowForParamsWithSameType;
}
public void setDoNotShowIfMethodNameContainsParameterName(boolean doNotShowIfMethodNameContainsParameterName) {
myIsDoNotShowIfMethodNameContainsParameterName = doNotShowIfMethodNameContainsParameterName;
}
public void setShowForParamsWithSameType(boolean showForParamsWithSameType) {
myIsShowForParamsWithSameType = showForParamsWithSameType;
}
@Nullable
@Override
public Element getState() {
Element root = new Element("settings");
if (!myRemovedPatterns.isEmpty() || !myAddedPatterns.isEmpty()) {
Element blacklists = getOrCreateChild(root, BLACKLISTS);
myRemovedPatterns.forEach((language, patterns) -> addLanguagePatternElements(blacklists, language, patterns, REMOVED));
myAddedPatterns.forEach((language, patterns) -> addLanguagePatternElements(blacklists, language, patterns, ADDED));
}
if (!myIsDoNotShowIfMethodNameContainsParameterName) {
getOrCreateChild(root, DO_NOT_SHOW_IF_PARAM_NAME_CONTAINED_IN_METHOD_NAME)
.setAttribute("value", String.valueOf(myIsDoNotShowIfMethodNameContainsParameterName));
}
if (myIsShowForParamsWithSameType) {
getOrCreateChild(root, SHOW_WHEN_MULTIPLE_PARAMS_WITH_SAME_TYPE).setAttribute("value", String.valueOf(myIsShowForParamsWithSameType));
}
return root;
}
@Override
public void loadState(Element state) {
myAddedPatterns.clear();
myRemovedPatterns.clear();
myIsDoNotShowIfMethodNameContainsParameterName = true;
myIsShowForParamsWithSameType = false;
List<Element> allBlackLists = JDOMUtil.getChildren(state.getChild(BLACKLISTS), LANGUAGE_LIST);
for (Element blacklist : allBlackLists) {
String language = attributeValue(blacklist, LANGUAGE);
if (language == null) {
continue;
}
myAddedPatterns.put(language, extractPatterns(blacklist, ADDED));
myRemovedPatterns.put(language, extractPatterns(blacklist, REMOVED));
}
myIsDoNotShowIfMethodNameContainsParameterName = getBooleanValue(state, DO_NOT_SHOW_IF_PARAM_NAME_CONTAINED_IN_METHOD_NAME, true);
myIsShowForParamsWithSameType = getBooleanValue(state, SHOW_WHEN_MULTIPLE_PARAMS_WITH_SAME_TYPE, false);
}
@NotNull
private Set<String> extractPatterns(Element element, String tag) {
List<Element> children = element.getChildren(tag);
return new LinkedHashSet<>(ContainerUtil.mapNotNull(children, it -> attributeValue(it, PATTERN)));
}
@Nullable
private String attributeValue(Element element, String attr) {
Attribute attribute = element.getAttribute(attr);
if (attribute == null) {
return null;
}
return attribute.getValue();
}
private static void addLanguagePatternElements(Element element, String language, Set<String> patterns, String tag) {
Element list = getOrCreateChild(element, LANGUAGE_LIST);
list.setAttribute(LANGUAGE, language);
List<Element> elements = ContainerUtil.map(patterns, it -> toPatternElement(it, tag));
list.addContent(elements);
}
private static Element toPatternElement(String pattern, String status) {
Element element = new Element(status);
element.setAttribute(PATTERN, pattern);
return element;
}
private static Element getOrCreateChild(Element element, String name) {
Element child = element.getChild(name);
if (child == null) {
child = new Element(name);
element.addContent(child);
}
return child;
}
private static boolean getBooleanValue(Element element, String childName, boolean defaultValue) {
Element child = element.getChild(childName);
if (child == null) {
return defaultValue;
}
String value = child.getAttributeValue("value");
if (value == null) {
return defaultValue;
}
return Boolean.parseBoolean(value);
}
@NotNull
private Set<String> getAddedPatterns(Language language) {
String key = language.getID();
Set<String> set = myAddedPatterns.get(key);
return set == null ? Collections.<String>emptySet() : set;
}
@NotNull
private Set<String> getRemovedPatterns(Language language) {
String key = language.getID();
Set<String> set = myRemovedPatterns.get(key);
return set == null ? Collections.<String>emptySet() : set;
}
private void setRemovedPatterns(Language language, Set<String> removed) {
String key = language.getID();
myRemovedPatterns.put(key, removed);
}
private void setAddedPatterns(Language language, Set<String> added) {
String key = language.getID();
myAddedPatterns.put(key, added);
}
}