From 5a17f77e466e4963876ae14ff0c847d084b3fe79 Mon Sep 17 00:00:00 2001 From: Rustam Vishnyakov Date: Thu, 9 Nov 2017 16:43:03 +0300 Subject: [PATCH] PSI file-based code style API --- .../application/options/CodeStyle.java | 152 ++++++++++++++++++ .../completion/InsertionContext.java | 4 +- .../enter/EnterInStringLiteralHandler.java | 7 +- .../FormattingDocumentModelImpl.java | 4 +- .../lineIndent/IndentCalculator.java | 8 +- .../openapi/editor/actions/TabAction.java | 4 +- .../codeInsight/PyMethodNameTypedHandler.java | 6 +- 7 files changed, 165 insertions(+), 20 deletions(-) create mode 100644 platform/lang-api/src/com/intellij/application/options/CodeStyle.java diff --git a/platform/lang-api/src/com/intellij/application/options/CodeStyle.java b/platform/lang-api/src/com/intellij/application/options/CodeStyle.java new file mode 100644 index 000000000000..4cd7ef695496 --- /dev/null +++ b/platform/lang-api/src/com/intellij/application/options/CodeStyle.java @@ -0,0 +1,152 @@ +// Copyright 2000-2017 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.intellij.application.options; + +import com.intellij.lang.Language; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiFile; +import com.intellij.psi.codeStyle.CodeStyleSettings; +import com.intellij.psi.codeStyle.CodeStyleSettingsManager; +import com.intellij.psi.codeStyle.CommonCodeStyleSettings; +import com.intellij.psi.codeStyle.CustomCodeStyleSettings; +import org.jetbrains.annotations.NotNull; + +/** + * Utility class for miscellaneous code style settings retrieving methods. + */ +public class CodeStyle { + + private CodeStyle() { + } + + /** + * @return Default application-wide root code style settings. + */ + @NotNull + public static CodeStyleSettings getDefaultSettings() { + return CodeStyleSettingsManager.getInstance().getCurrentSettings(); + } + + /** + * Returns root code style settings for the given project. For configurable language settings use {@link #getLanguageSettings(PsiFile)} or + * {@link #getLanguageSettings(PsiFile, Language)}. + * @param project The project to get code style settings for. + * @return The current root code style settings associated with the project. + */ + @NotNull + public static CodeStyleSettings getSettings(@NotNull Project project) { + return CodeStyleSettingsManager.getInstance(project).getCurrentSettings(); + } + + /** + * Returns root code style settings for the given PSI file. For configurable language settings use {@link #getLanguageSettings(PsiFile)} or + * {@link #getLanguageSettings(PsiFile, Language)}. + * @param file The file to get code style settings for. + * @return The current root code style settings associated with the file or default settings if the file is invalid. + */ + @NotNull + public static CodeStyleSettings getSettings(@NotNull PsiFile file) { + if (file.isValid()) { + Project project = file.getProject(); + return CodeStyleSettingsManager.getInstance(project).getCurrentSettings(); + } + return getDefaultSettings(); + } + + /** + * Returns custom settings for the given PSI file. + * @param file The file. + * @param customSettingsClass The class of a settings object to be returned. + * @param Settings class type. + * @return The current custom settings associated with the PSI file. + */ + @NotNull + public static T getCustomSettings(@NotNull PsiFile file, Class customSettingsClass) { + CodeStyleSettings rootSettings = getSettings(file); + return rootSettings.getCustomSettings(customSettingsClass); + } + + /** + * Returns language settings for the given PSI file. The language is taken from the file itself. + * @param file The file to retrieve language settings for. + * @return The associated language settings. + */ + @NotNull + public static CommonCodeStyleSettings getLanguageSettings(@NotNull PsiFile file) { + CodeStyleSettings rootSettings = getSettings(file); + return rootSettings.getCommonSettings(file.getLanguage()); + } + + /** + * Returns language settings for the given PSI file and language. This method may be useful when PSI file contains elements for multiple + * languages and language settings should be taken from a specific language context. + * @param file The file to retrieve language settings for. + * @return The associated language settings. + */ + public static CommonCodeStyleSettings getLanguageSettings(@NotNull PsiFile file, @NotNull Language language) { + CodeStyleSettings rootSettings = getSettings(file); + return rootSettings.getCommonSettings(language); + } + + /** + * Returns indent options for the given PSI file. The method attempts to use {@link com.intellij.psi.codeStyle.FileIndentOptionsProvider} + * if applicable to the file. If there are no suitable indent options providers, it takes configurable language indent options or + * retrieves indent options by file type. + * @param file The file to get indent options for. + * @return The file indent options. + * @see com.intellij.psi.codeStyle.FileIndentOptionsProvider + */ + @NotNull + public static CommonCodeStyleSettings.IndentOptions getIndentOptions(@NotNull PsiFile file) { + CodeStyleSettings rootSettings = getSettings(file); + return rootSettings.getIndentOptionsByFile(file); + } + + /** + * Explicitly retrieves indent options by file type. + * @param file The file to get indent options for. + * @return The indent options associated with the file type. + */ + @NotNull + public static CommonCodeStyleSettings.IndentOptions getIndentOptionsByFileType(@NotNull PsiFile file) { + return getSettings(file).getIndentOptions(file.getFileType()); + } + + /** + * Returns indent options for the given project and document. + * @param project The current project. + * @param document The document to get indent options for. + * @return The indent options associated with document's PSI file if the file is available or other indent options otherwise. + */ + @NotNull + public static CommonCodeStyleSettings.IndentOptions getIndentOptions(@NotNull Project project, @NotNull Document document) { + PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(document); + if (file != null) { + return getIndentOptions(file); + } + return getSettings(project).getIndentOptions(null); + } + + /** + * Returns indent size for the given PSI file. + * @param file The file to get indent size for. + * @return The indent size to be used with the PSI file. + */ + public static int getIndentSize(@NotNull PsiFile file) { + return getIndentOptions(file).INDENT_SIZE; + } + +} diff --git a/platform/lang-api/src/com/intellij/codeInsight/completion/InsertionContext.java b/platform/lang-api/src/com/intellij/codeInsight/completion/InsertionContext.java index cc394daf7645..41296771d831 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/completion/InsertionContext.java +++ b/platform/lang-api/src/com/intellij/codeInsight/completion/InsertionContext.java @@ -15,6 +15,7 @@ */ package com.intellij.codeInsight.completion; +import com.intellij.application.options.CodeStyle; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.lang.Language; import com.intellij.openapi.editor.Document; @@ -22,7 +23,6 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; -import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.psi.codeStyle.CommonCodeStyleSettings; import com.intellij.psi.util.PsiUtilCore; import org.jetbrains.annotations.NotNull; @@ -139,6 +139,6 @@ public class InsertionContext { public CommonCodeStyleSettings getCodeStyleSettings() { Language lang = PsiUtilCore.getLanguageAtOffset(getFile(), getTailOffset()); - return CodeStyleSettingsManager.getSettings(getProject()).getCommonSettings(lang); + return CodeStyle.getLanguageSettings(getFile(), lang); } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/enter/EnterInStringLiteralHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/enter/EnterInStringLiteralHandler.java index cb742a2ea594..2ae23e6bf23f 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/enter/EnterInStringLiteralHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/enter/EnterInStringLiteralHandler.java @@ -16,6 +16,7 @@ package com.intellij.codeInsight.editorActions.enter; +import com.intellij.application.options.CodeStyle; import com.intellij.codeInsight.editorActions.EnterHandler; import com.intellij.codeInsight.editorActions.JavaLikeQuoteHandler; import com.intellij.codeInsight.editorActions.QuoteHandler; @@ -37,8 +38,6 @@ import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.StringEscapesTokenTypes; -import com.intellij.psi.codeStyle.CodeStyleSettingsManager; -import com.intellij.psi.codeStyle.CommonCodeStyleSettings; import org.jetbrains.annotations.NotNull; public class EnterInStringLiteralHandler extends EnterHandlerDelegateAdapter { @@ -86,9 +85,7 @@ public class EnterInStringLiteralHandler extends EnterHandlerDelegateAdapter { document.insertString(caretOffset, insertedFragment + " " + literalStart); caretOffset += insertedFragment.length(); caretAdvance = 1; - CommonCodeStyleSettings langSettings = - CodeStyleSettingsManager.getSettings(file.getProject()).getCommonSettings(file.getLanguage()); - if (langSettings.BINARY_OPERATION_SIGN_ON_NEXT_LINE) { + if (CodeStyle.getLanguageSettings(file).BINARY_OPERATION_SIGN_ON_NEXT_LINE) { caretOffset -= 1; caretAdvance = 3; } diff --git a/platform/lang-impl/src/com/intellij/psi/formatter/FormattingDocumentModelImpl.java b/platform/lang-impl/src/com/intellij/psi/formatter/FormattingDocumentModelImpl.java index 84b81a28b191..add62968ae9a 100644 --- a/platform/lang-impl/src/com/intellij/psi/formatter/FormattingDocumentModelImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/formatter/FormattingDocumentModelImpl.java @@ -16,6 +16,7 @@ package com.intellij.psi.formatter; +import com.intellij.application.options.CodeStyle; import com.intellij.formatting.FormattingDocumentModel; import com.intellij.lang.ASTNode; import com.intellij.lang.Language; @@ -28,7 +29,6 @@ import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.codeStyle.CodeStyleSettings; -import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.psi.impl.DebugUtil; import com.intellij.psi.impl.PsiDocumentManagerImpl; import com.intellij.psi.impl.PsiToDocumentSynchronizer; @@ -50,7 +50,7 @@ public class FormattingDocumentModelImpl implements FormattingDocumentModel { myFile = file; Language language = file.getLanguage(); myWhiteSpaceStrategy = WhiteSpaceFormattingStrategyFactory.getStrategy(language); - mySettings = CodeStyleSettingsManager.getSettings(file.getProject()); + mySettings = CodeStyle.getSettings(file); } public static FormattingDocumentModelImpl createOn(@NotNull PsiFile file) { diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/lineIndent/IndentCalculator.java b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/lineIndent/IndentCalculator.java index ffc408ef2fbe..a13f4ff94ad4 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/lineIndent/IndentCalculator.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/lineIndent/IndentCalculator.java @@ -15,6 +15,7 @@ */ package com.intellij.psi.impl.source.codeStyle.lineIndent; +import com.intellij.application.options.CodeStyle; import com.intellij.formatting.Indent; import com.intellij.formatting.IndentInfo; import com.intellij.lang.Language; @@ -23,8 +24,6 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; -import com.intellij.psi.codeStyle.CodeStyleSettings; -import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.psi.codeStyle.CommonCodeStyleSettings; import com.intellij.psi.impl.source.codeStyle.SemanticEditorPosition; import com.intellij.util.text.CharArrayUtil; @@ -71,11 +70,10 @@ public class IndentCalculator { Document document = myEditor.getDocument(); PsiFile file = PsiDocumentManager.getInstance(myProject).getPsiFile(document); if (file != null) { - CodeStyleSettings codeStyleSettings = CodeStyleSettingsManager.getSettings(myProject); - CommonCodeStyleSettings.IndentOptions fileOptions = codeStyleSettings.getIndentOptionsByFile(file); + CommonCodeStyleSettings.IndentOptions fileOptions = CodeStyle.getIndentOptions(file); CommonCodeStyleSettings.IndentOptions options = !fileOptions.isOverrideLanguageOptions() && language != null && !(language.is(file.getLanguage()) || language.is(Language.ANY)) ? - codeStyleSettings.getCommonSettings(language).getIndentOptions() : + CodeStyle.getLanguageSettings(file, language).getIndentOptions() : fileOptions; return baseIndent + new IndentInfo(0, indentTypeToSize(myIndentType, options), 0, false).generateNewWhiteSpace(options); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/TabAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/TabAction.java index e57948388ed2..bc6674c3ba17 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/TabAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/TabAction.java @@ -16,6 +16,7 @@ package com.intellij.openapi.editor.actions; +import com.intellij.application.options.CodeStyle; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.command.CommandProcessor; @@ -28,7 +29,6 @@ import com.intellij.openapi.editor.ex.util.EditorUIUtil; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.codeStyle.CodeStyleSettings; -import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.psi.codeStyle.CommonCodeStyleSettings; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -71,7 +71,7 @@ public class TabAction extends EditorAction { columnNumber = editor.getCaretModel().getLogicalPosition().column; } - CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(project); + CodeStyleSettings settings = project != null ? CodeStyle.getSettings(project) : CodeStyle.getDefaultSettings(); final Document doc = editor.getDocument(); CommonCodeStyleSettings.IndentOptions indentOptions = settings.getIndentOptionsByDocument(project, doc); diff --git a/python/src/com/jetbrains/python/codeInsight/PyMethodNameTypedHandler.java b/python/src/com/jetbrains/python/codeInsight/PyMethodNameTypedHandler.java index 01058d4a0805..1851e65d9b40 100644 --- a/python/src/com/jetbrains/python/codeInsight/PyMethodNameTypedHandler.java +++ b/python/src/com/jetbrains/python/codeInsight/PyMethodNameTypedHandler.java @@ -15,6 +15,7 @@ */ package com.jetbrains.python.codeInsight; +import com.intellij.application.options.CodeStyle; import com.intellij.codeInsight.editorActions.TypedHandlerDelegate; import com.intellij.lang.ASTNode; import com.intellij.openapi.editor.Document; @@ -27,8 +28,6 @@ import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; -import com.intellij.psi.codeStyle.CodeStyleSettings; -import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.psi.codeStyle.CommonCodeStyleSettings; import com.jetbrains.python.PyNames; import com.jetbrains.python.PyTokenTypes; @@ -95,8 +94,7 @@ public class PyMethodNameTypedHandler extends TypedHandlerDelegate { paramName = ""; } // TODO: only print the ")" if Settings require it - final CodeStyleSettings settingsManager = CodeStyleSettingsManager.getSettings(project); - final CommonCodeStyleSettings settings = settingsManager.getCommonSettings(PythonLanguage.getInstance()); + final CommonCodeStyleSettings settings = CodeStyle.getLanguageSettings(file, PythonLanguage.getInstance()); final StringBuilder textToType = new StringBuilder(); textToType.append("("); if (!paramName.isEmpty()) {