cleanup
[idea/community.git] / platform / platform-api / src / com / intellij / lang / Language.java
1 /*
2  * Copyright 2000-2009 JetBrains s.r.o.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 package com.intellij.lang;
17
18 import com.intellij.openapi.diagnostic.Logger;
19 import com.intellij.openapi.fileTypes.FileType;
20 import com.intellij.openapi.fileTypes.FileTypeManager;
21 import com.intellij.openapi.fileTypes.LanguageFileType;
22 import com.intellij.openapi.util.UserDataHolderBase;
23 import com.intellij.util.ArrayUtil;
24 import gnu.trove.THashMap;
25 import org.jetbrains.annotations.NonNls;
26 import org.jetbrains.annotations.NotNull;
27 import org.jetbrains.annotations.Nullable;
28
29 import java.util.Collection;
30 import java.util.Collections;
31 import java.util.Map;
32
33 /**
34  * The base class for all programming language support implementations. Specific language implementations should inherit from this class
35  * and its register instance wrapped with {@link com.intellij.openapi.fileTypes.LanguageFileType} instance through
36  * <code>FileTypeManager.getInstance().registerFileType</code>
37  * There should be exactly one instance of each Language. It is usually created when creating {@link com.intellij.openapi.fileTypes.LanguageFileType} and can be retrieved later
38  * with {@link #findInstance(Class)}.
39  * For the list of standard languages, see {@link com.intellij.lang.StdLanguages}.
40  */
41 public abstract class Language extends UserDataHolderBase {
42   private static final Logger LOG = Logger.getInstance("#com.intellij.lang.Language");
43
44   private static final Map<Class<? extends Language>, Language> ourRegisteredLanguages = new THashMap<Class<? extends Language>, Language>();
45   private static final Map<String, Language> ourRegisteredIDs = new THashMap<String, Language>();
46   private final Language myBaseLanguage;
47   private final String myID;
48   private final String[] myMimeTypes;
49   public static final Language ANY = new Language("") {
50     @Override
51     public String toString() {
52       //noinspection HardCodedStringLiteral
53       return "Language: ANY";
54     }
55   };
56
57   protected Language(@NotNull @NonNls String id) {
58     this(id, ArrayUtil.EMPTY_STRING_ARRAY);
59   }
60
61   protected Language(@NotNull @NonNls final String ID, @NotNull @NonNls final String... mimeTypes) {
62     this(null, ID, mimeTypes);
63   }
64
65   protected Language(@Nullable Language baseLanguage, @NotNull @NonNls final String ID, @NotNull @NonNls final String... mimeTypes) {
66     myBaseLanguage = baseLanguage;
67     myID = ID;
68     myMimeTypes = mimeTypes;
69     Class<? extends Language> langClass = getClass();
70     Language prev = ourRegisteredLanguages.put(langClass, this);
71     if (prev != null) {
72       LOG.error("Language of '" + langClass + "' is already registered: "+prev);
73       return;
74     }
75     prev = ourRegisteredIDs.put(ID, this);
76     if (prev != null) {
77       LOG.error("Language with ID '" + ID + "' is already registered: "+prev.getClass());
78     }
79   }
80
81   /**
82    * @return collection of all languages registered so far.
83    */
84   public static Collection<Language> getRegisteredLanguages() {
85     return Collections.unmodifiableCollection(ourRegisteredLanguages.values());
86   }
87
88   /**
89    * @param klass <code>java.lang.Class</code> of the particular language. Serves key purpose.
90    * @return instance of the <code>klass</code> language registered if any.
91    */
92   public static <T extends Language> T findInstance(Class<T> klass) {
93     //noinspection unchecked
94     return (T)ourRegisteredLanguages.get(klass);
95   }
96
97
98   public String toString() {
99     //noinspection HardCodedStringLiteral
100     return "Language: " + myID;
101   }
102
103   /**
104    * Returns the list of MIME types corresponding to the language. The language MIME type is used for specifying the base language
105    * of a JSP page.
106    *
107    * @return The list of MIME types.
108    */
109   @NotNull
110   public String[] getMimeTypes() {
111     return myMimeTypes;
112   }
113
114   /**
115    * Returns a user-readable name of the language.
116    *
117    * @return the name of the language.
118    */
119   @NotNull
120   public String getID() {
121     return myID;
122   }
123
124   @Nullable
125   public LanguageFileType getAssociatedFileType() {
126     final FileType[] types = FileTypeManager.getInstance().getRegisteredFileTypes();
127     for (final FileType fileType : types) {
128       if (fileType instanceof LanguageFileType && ((LanguageFileType)fileType).getLanguage() == this) {
129         return (LanguageFileType)fileType;
130       }
131     }
132     for (final FileType fileType : types) {
133       if (fileType instanceof LanguageFileType && isKindOf(((LanguageFileType)fileType).getLanguage())) {
134         return (LanguageFileType) fileType;
135       }
136     }
137     return null;
138   }
139
140   @Nullable
141   public Language getBaseLanguage() {
142     return myBaseLanguage;
143   }
144
145   public String getDisplayName() {
146     return getID();
147   }
148
149   public final boolean is(Language another) {
150     return this == another;
151   }
152
153   public boolean isCaseSensitive() {
154     return myBaseLanguage != null && myBaseLanguage.isCaseSensitive();
155   }
156
157   public final boolean isKindOf(Language another) {
158     Language l = this;
159     while (l != null) {
160       if (l.is(another)) return true;
161       l = l.getBaseLanguage();
162     }
163     return false;
164   }
165
166   @Nullable
167   public static Language findLanguageByID(String id) {
168     final Collection<Language> languages = getRegisteredLanguages();
169     for (Language language : languages) {
170       if (language.getID().equals(id)) {
171         return language;
172       }
173     }
174     return null;
175   }
176 }