2 * Copyright 2000-2012 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package com.intellij.codeInsight.daemon.impl.analysis;
19 import com.intellij.openapi.application.ApplicationManager;
20 import com.intellij.openapi.components.*;
21 import com.intellij.openapi.project.DumbService;
22 import com.intellij.openapi.project.Project;
23 import com.intellij.openapi.project.ProjectCoreUtil;
24 import com.intellij.openapi.roots.ProjectFileIndex;
25 import com.intellij.openapi.roots.ProjectRootManager;
26 import com.intellij.openapi.vfs.VirtualFile;
27 import com.intellij.openapi.vfs.VirtualFileManager;
28 import com.intellij.psi.PsiElement;
29 import com.intellij.psi.PsiFile;
30 import com.intellij.psi.SingleRootFileViewProvider;
31 import com.intellij.psi.search.ProjectScope;
32 import com.intellij.psi.util.PsiUtilBase;
33 import org.jdom.Element;
34 import org.jetbrains.annotations.NonNls;
35 import org.jetbrains.annotations.NotNull;
39 @State(name="HighlightingSettingsPerFile", storages = @Storage(file = StoragePathMacros.WORKSPACE_FILE))
40 public class HighlightingSettingsPerFile extends HighlightingLevelManager implements PersistentStateComponent<Element> {
41 @NonNls private static final String SETTING_TAG = "setting";
42 @NonNls private static final String ROOT_ATT_PREFIX = "root";
43 @NonNls private static final String FILE_ATT = "file";
45 public static HighlightingSettingsPerFile getInstance(Project project){
46 return (HighlightingSettingsPerFile)ServiceManager.getService(project, HighlightingLevelManager.class);
49 private final Map<VirtualFile, FileHighlightingSetting[]> myHighlightSettings = new HashMap<VirtualFile, FileHighlightingSetting[]>();
52 public FileHighlightingSetting getHighlightingSettingForRoot(@NotNull PsiElement root){
53 final PsiFile containingFile = root.getContainingFile();
54 final VirtualFile virtualFile = containingFile.getVirtualFile();
55 FileHighlightingSetting[] fileHighlightingSettings = myHighlightSettings.get(virtualFile);
56 final int index = PsiUtilBase.getRootIndex(root);
58 if(fileHighlightingSettings == null || fileHighlightingSettings.length <= index) {
59 return getDefaultHighlightingSetting(root.getProject(), virtualFile);
61 return fileHighlightingSettings[index];
65 private static FileHighlightingSetting getDefaultHighlightingSetting(@NotNull Project project, final VirtualFile virtualFile) {
66 if (virtualFile != null) {
67 DefaultHighlightingSettingProvider[] providers = DefaultHighlightingSettingProvider.EP_NAME.getExtensions();
68 List<DefaultHighlightingSettingProvider> filtered = DumbService.getInstance(project).filterByDumbAwareness(providers);
69 for (DefaultHighlightingSettingProvider p : filtered) {
70 FileHighlightingSetting setting = p.getDefaultSetting(project, virtualFile);
71 if (setting != null) {
76 return FileHighlightingSetting.FORCE_HIGHLIGHTING;
80 private static FileHighlightingSetting[] getDefaults(@NotNull PsiFile file){
81 final int rootsCount = file.getViewProvider().getLanguages().size();
82 final FileHighlightingSetting[] fileHighlightingSettings = new FileHighlightingSetting[rootsCount];
83 for (int i = 0; i < fileHighlightingSettings.length; i++) {
84 fileHighlightingSettings[i] = FileHighlightingSetting.FORCE_HIGHLIGHTING;
86 return fileHighlightingSettings;
89 public void setHighlightingSettingForRoot(@NotNull PsiElement root, @NotNull FileHighlightingSetting setting) {
90 final PsiFile containingFile = root.getContainingFile();
91 final VirtualFile virtualFile = containingFile.getVirtualFile();
92 if (virtualFile == null) return;
93 FileHighlightingSetting[] defaults = myHighlightSettings.get(virtualFile);
94 int rootIndex = PsiUtilBase.getRootIndex(root);
95 if (defaults != null && rootIndex >= defaults.length) defaults = null;
96 if (defaults == null) defaults = getDefaults(containingFile);
97 defaults[rootIndex] = setting;
98 boolean toRemove = true;
99 for (FileHighlightingSetting aDefault : defaults) {
100 if (aDefault != FileHighlightingSetting.NONE) toRemove = false;
103 myHighlightSettings.remove(virtualFile);
106 myHighlightSettings.put(virtualFile, defaults);
111 public void loadState(Element element) {
112 List children = element.getChildren(SETTING_TAG);
113 for (final Object aChildren : children) {
114 final Element child = (Element)aChildren;
115 final String url = child.getAttributeValue(FILE_ATT);
116 if (url == null) continue;
117 final VirtualFile fileByUrl = VirtualFileManager.getInstance().findFileByUrl(url);
118 if (fileByUrl != null) {
119 final List<FileHighlightingSetting> settings = new ArrayList<FileHighlightingSetting>();
121 while (child.getAttributeValue(ROOT_ATT_PREFIX + index) != null) {
122 final String attributeValue = child.getAttributeValue(ROOT_ATT_PREFIX + index++);
123 settings.add(Enum.valueOf(FileHighlightingSetting.class, attributeValue));
125 myHighlightSettings.put(fileByUrl, settings.toArray(new FileHighlightingSetting[settings.size()]));
131 public Element getState() {
132 final Element element = new Element("state");
133 for (Map.Entry<VirtualFile, FileHighlightingSetting[]> entry : myHighlightSettings.entrySet()) {
134 final Element child = new Element(SETTING_TAG);
136 final VirtualFile vFile = entry.getKey();
137 if (!vFile.isValid()) continue;
138 child.setAttribute(FILE_ATT, vFile.getUrl());
139 for (int i = 0; i < entry.getValue().length; i++) {
140 final FileHighlightingSetting fileHighlightingSetting = entry.getValue()[i];
141 child.setAttribute(ROOT_ATT_PREFIX + i, fileHighlightingSetting.toString());
143 element.addContent(child);
149 public boolean shouldHighlight(@NotNull PsiElement psiRoot) {
150 final FileHighlightingSetting settingForRoot = getHighlightingSettingForRoot(psiRoot);
151 return settingForRoot != FileHighlightingSetting.SKIP_HIGHLIGHTING;
155 public boolean shouldInspect(@NotNull PsiElement psiRoot) {
156 if (ApplicationManager.getApplication().isUnitTestMode()) return true;
158 final FileHighlightingSetting settingForRoot = getHighlightingSettingForRoot(psiRoot);
159 if (settingForRoot == FileHighlightingSetting.SKIP_HIGHLIGHTING ||
160 settingForRoot == FileHighlightingSetting.SKIP_INSPECTION) {
163 final Project project = psiRoot.getProject();
164 final VirtualFile virtualFile = psiRoot.getContainingFile().getVirtualFile();
165 if (virtualFile == null || !virtualFile.isValid()) return false;
167 if (ProjectCoreUtil.isProjectOrWorkspaceFile(virtualFile)) return false;
169 final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex();
170 if (ProjectScope.getLibrariesScope(project).contains(virtualFile) && !fileIndex.isInContent(virtualFile)) return false;
172 return !SingleRootFileViewProvider.isTooLargeForIntelligence(virtualFile);