blob: b885101bde752fcedfca96bf743231eb035e3cda [file] [log] [blame]
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* 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.maddyhome.idea.copyright.util;
import com.intellij.lang.Commenter;
import com.intellij.lang.LanguageCommenters;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileTypes.*;
import com.intellij.openapi.project.ProjectCoreUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiFile;
import com.intellij.util.messages.MessageBus;
import com.maddyhome.idea.copyright.CopyrightUpdaters;
import com.maddyhome.idea.copyright.options.LanguageOptions;
import org.jetbrains.annotations.NotNull;
import java.util.*;
public class FileTypeUtil {
public static synchronized FileTypeUtil getInstance() {
return ServiceManager.getService(FileTypeUtil.class);
}
public FileTypeUtil(MessageBus bus) {
createMappings();
bus.connect().subscribe(FileTypeManager.TOPIC, new FileTypeListener.Adapter() {
@Override
public void fileTypesChanged(@NotNull FileTypeEvent event) {
types = null;
}
});
}
public static String buildComment(FileType type, String template, LanguageOptions options) {
Commenter commenter = getCommenter(type);
if (commenter == null) {
return "<No comments>";
}
String bs = commenter.getBlockCommentPrefix();
String be = commenter.getBlockCommentSuffix();
String ls = commenter.getLineCommentPrefix();
if ((bs == null || be == null) && ls == null) {
return "<No comments>";
}
boolean allowBlock = bs != null && be != null;
boolean allowLine = ls != null;
if (allowLine && !allowBlock) {
bs = ls;
be = ls;
}
boolean allowSeparator = getInstance().allowSeparators(type);
String filler = options.getFiller();
if (!allowSeparator) {
if (options.getFiller() == LanguageOptions.DEFAULT_FILLER) {
filler = "~";
}
}
boolean isBlock = options.isBlock();
boolean isPrefix = options.isPrefixLines();
if (isBlock && !allowBlock) {
isPrefix = true;
}
boolean isBox = options.isBox() && options.isSeparateBefore() && options.isSeparateAfter() &&
options.getLenBefore() == options.getLenAfter();
StringBuilder preview = new StringBuilder(80);
String open = isBlock ? bs : allowLine ? ls : bs;
String close = isBlock ? be : allowLine ? ls : be;
StringBuilder pre = new StringBuilder(5);
StringBuilder leader = new StringBuilder(5);
StringBuilder post = new StringBuilder(5);
if (filler == LanguageOptions.DEFAULT_FILLER) {
filler = open.substring(open.length() - 1);
}
int offset = 0;
if (isBlock) {
int pos = open.length() - 1;
pre.append(allowBlock ? filler : open.charAt(pos));
while (pos > 0 && open.charAt(pos) == open.charAt(open.length() - 1)) {
pos--;
offset++;
}
while (open.length() > 1 && pos >= 0) {
leader.append(' ');
pos--;
}
post.append(filler);
if (!isPrefix) {
pre = new StringBuilder(0);
}
if (!allowBlock) {
close = filler;
}
}
else {
if (allowLine) {
close = filler;
}
pre.append(open);
post.append(close);
}
int diff = 0;
if (options.isSeparateBefore()) {
if (isBlock && isBox && allowBlock) {
diff = close.length() - offset;
}
preview.append(open);
for (int i = open.length() + 1; i <= options.getLenBefore() - diff - post.length(); i++) {
preview.append(filler);
}
preview.append(post);
preview.append('\n');
}
else if (isBlock) {
preview.append(open).append('\n');
}
if (template.length() > 0) {
String[] lines = template.split("\n", -1);
for (String line : lines) {
if (options.isTrim()) {
line = line.trim();
}
line = StringUtil.trimStart(StringUtil.trimStart(line, pre.toString()), open);
line = StringUtil.trimEnd(line, close);
preview.append(leader).append(pre);
int len = 0;
if (pre.length() > 0 && line.length() > 0) {
preview.append(' ');
len++;
}
preview.append(line);
len += line.length() + leader.length() + pre.length();
if (isBox && len < options.getLenBefore() - diff) {
for (; len < options.getLenBefore() - diff - post.length(); len++) {
preview.append(' ');
}
if (isBlock || allowLine) {
preview.append(post.substring(0, options.getLenBefore() - diff - len));
}
}
if (!isBlock && !allowLine) {
if (preview.charAt(preview.length() - 1) != ' ') {
preview.append(' ');
}
preview.append(close);
}
preview.append('\n');
}
}
preview.append(leader);
if (options.isSeparateAfter()) {
preview.append(pre);
for (int i = leader.length() + pre.length(); i < options.getLenAfter() - close.length(); i++) {
preview.append(filler);
}
preview.append(close);
preview.append('\n');
}
else if (isBlock) {
if (!allowBlock) {
preview.append(pre).append('\n');
}
else {
preview.append(close).append('\n');
}
}
return preview.substring(0, preview.length() - 1);
}
public boolean isSupportedFile(VirtualFile file) {
if (file == null || file.isDirectory()) {
return false;
}
if (ProjectCoreUtil.isProjectOrWorkspaceFile(file)) return false;
FileType type = file.getFileType();
return getMap().get(type.getName()) != null;
}
public static boolean isSupportedFile(PsiFile file) {
if (file == null || file instanceof PsiDirectory) {
return false;
}
final VirtualFile virtualFile = file.getVirtualFile();
if (virtualFile == null) return false;
if (ProjectCoreUtil.isProjectOrWorkspaceFile(virtualFile)) return false;
return isSupportedType(virtualFile.getFileType());
}
public FileType[] getSupportedTypes() {
HashSet<FileType> set = new HashSet<FileType>(getMap().values());
return set.toArray(new FileType[set.size()]);
}
public FileType getFileTypeByFile(VirtualFile file) {
FileType type = file.getFileType();
return getFileTypeByType(type);
}
public FileType getFileTypeByType(FileType type) {
return getMap().get(type.getName());
}
public String getFileTypeNameByName(String name) {
FileType type = getMap().get(name);
return type != null ? type.getName() : name;
}
public static boolean hasBlockComment(FileType fileType) {
Commenter commenter = getCommenter(fileType);
return commenter != null && commenter.getBlockCommentPrefix() != null;
}
public static boolean hasLineComment(FileType fileType) {
Commenter commenter = getCommenter(fileType);
return commenter != null && commenter.getLineCommentPrefix() != null;
}
public boolean allowSeparators(FileType fileType) {
FileType type = getFileTypeByType(fileType);
return !noSeparators.contains(type);
}
private static Commenter getCommenter(FileType fileType) {
if (fileType instanceof LanguageFileType) {
return LanguageCommenters.INSTANCE.forLanguage(((LanguageFileType)fileType).getLanguage());
}
return null;
}
private void createMappings() {
Set<FileType> maps = new HashSet<FileType>();
maps.add(StdFileTypes.DTD);
maps.add(StdFileTypes.XML);
mappings.put(StdFileTypes.XML, maps);
maps = new HashSet<FileType>();
maps.add(StdFileTypes.HTML);
maps.add(StdFileTypes.XHTML);
mappings.put(StdFileTypes.HTML, maps);
maps = new HashSet<FileType>();
maps.add(StdFileTypes.JSP);
mappings.put(StdFileTypes.JSP, maps);
noSeparators.add(StdFileTypes.XML);
noSeparators.add(StdFileTypes.HTML);
noSeparators.add(StdFileTypes.JSP);
noSeparators.add(StdFileTypes.JSPX);
}
private static boolean isSupportedType(FileType type) {
if (type.isBinary() || type.getName().indexOf("IDEA") >= 0 || "GUI_DESIGNER_FORM".equals(type.getName())) {
return false;
}
else {
Commenter commenter = getCommenter(type);
boolean hasComment = commenter != null &&
(commenter.getLineCommentPrefix() != null || commenter.getBlockCommentPrefix() != null);
if (!hasComment) {
return false;
}
if (type.equals(StdFileTypes.DTD)) {
return true;
}
if (type.equals(StdFileTypes.HTML)) {
return true;
}
if (type.equals(StdFileTypes.XHTML)) {
return true;
}
if (type.equals(StdFileTypes.PROPERTIES)) {
return true;
}
if ("JavaScript".equals(type.getName())) {
return true;
}
return CopyrightUpdaters.INSTANCE.forFileType(type) != null;
}
}
private void loadFileTypes() {
logger.debug("loadFileTypes");
Map<String, FileType> map = new HashMap<String, FileType>();
for (FileType ftype : FileTypeManager.getInstance().getRegisteredFileTypes()) {
// Ignore binary files
// Ignore IDEA specific file types (PROJECT, MODULE, WORKSPACE)
// Ignore GUI Designer files
if (isSupportedType(ftype)) {
logger.debug("adding " + ftype.getName());
Iterator<FileType> iter = mappings.keySet().iterator();
FileType type = ftype;
while (iter.hasNext()) {
FileType fileType = iter.next();
Set<FileType> maps = mappings.get(fileType);
if (maps.contains(ftype)) {
type = fileType;
break;
}
}
map.put(ftype.getName(), type);
}
else {
logger.debug("ignoring " + ftype.getName());
}
}
types = map;
}
public FileType getFileTypeByName(String name) {
return getMap().get(name);
}
@NotNull
private Map<String, FileType> getMap() {
if (types == null) loadFileTypes();
return types;
}
public static class SortByName implements Comparator<FileType> {
@Override
public int compare(FileType a, FileType b) {
return a.getName().compareToIgnoreCase(b.getName());
}
}
private Map<String, FileType> types;
private final Map<FileType, Set<FileType>> mappings = new HashMap<FileType, Set<FileType>>();
private final Set<FileType> noSeparators = new HashSet<FileType>();
private static final Logger logger = Logger.getInstance(FileTypeUtil.class.getName());
}