2 * Copyright 2000-2009 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.
16 package com.intellij.lang;
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;
29 import java.util.Collection;
30 import java.util.Collections;
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}.
41 public abstract class Language extends UserDataHolderBase {
42 private static final Logger LOG = Logger.getInstance("#com.intellij.lang.Language");
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("") {
51 public String toString() {
52 //noinspection HardCodedStringLiteral
53 return "Language: ANY";
57 protected Language(@NotNull @NonNls String id) {
58 this(id, ArrayUtil.EMPTY_STRING_ARRAY);
61 protected Language(@NotNull @NonNls final String ID, @NotNull @NonNls final String... mimeTypes) {
62 this(null, ID, mimeTypes);
65 protected Language(@Nullable Language baseLanguage, @NotNull @NonNls final String ID, @NotNull @NonNls final String... mimeTypes) {
66 myBaseLanguage = baseLanguage;
68 myMimeTypes = mimeTypes;
69 Class<? extends Language> langClass = getClass();
70 Language prev = ourRegisteredLanguages.put(langClass, this);
72 LOG.error("Language of '" + langClass + "' is already registered: "+prev);
75 prev = ourRegisteredIDs.put(ID, this);
77 LOG.error("Language with ID '" + ID + "' is already registered: "+prev.getClass());
82 * @return collection of all languages registered so far.
84 public static Collection<Language> getRegisteredLanguages() {
85 return Collections.unmodifiableCollection(ourRegisteredLanguages.values());
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.
92 public static <T extends Language> T findInstance(Class<T> klass) {
93 //noinspection unchecked
94 return (T)ourRegisteredLanguages.get(klass);
98 public String toString() {
99 //noinspection HardCodedStringLiteral
100 return "Language: " + myID;
104 * Returns the list of MIME types corresponding to the language. The language MIME type is used for specifying the base language
107 * @return The list of MIME types.
110 public String[] getMimeTypes() {
115 * Returns a user-readable name of the language.
117 * @return the name of the language.
120 public String getID() {
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;
132 for (final FileType fileType : types) {
133 if (fileType instanceof LanguageFileType && isKindOf(((LanguageFileType)fileType).getLanguage())) {
134 return (LanguageFileType) fileType;
141 public Language getBaseLanguage() {
142 return myBaseLanguage;
145 public String getDisplayName() {
149 public final boolean is(Language another) {
150 return this == another;
153 public boolean isCaseSensitive() {
154 return myBaseLanguage != null && myBaseLanguage.isCaseSensitive();
157 public final boolean isKindOf(Language another) {
160 if (l.is(another)) return true;
161 l = l.getBaseLanguage();
167 public static Language findLanguageByID(String id) {
168 final Collection<Language> languages = getRegisteredLanguages();
169 for (Language language : languages) {
170 if (language.getID().equals(id)) {