mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
InspectionSchemeTest
This commit is contained in:
@@ -53,5 +53,6 @@
|
||||
<orderEntry type="module" module-name="xml-psi-impl" />
|
||||
<orderEntry type="library" scope="TEST" name="KotlinTest" level="project" />
|
||||
<orderEntry type="module" module-name="built-in-server-api" scope="TEST" />
|
||||
<orderEntry type="module" module-name="configuration-store-impl" scope="TEST" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -30,6 +30,7 @@ import com.intellij.profile.codeInspection.InspectionProfileManager;
|
||||
import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
|
||||
import com.intellij.profile.codeInspection.ui.header.InspectionToolsConfigurable;
|
||||
import com.intellij.testFramework.LightIdeaTestCase;
|
||||
import com.intellij.util.JdomKt;
|
||||
import org.jdom.Element;
|
||||
import org.jdom.JDOMException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -74,9 +75,7 @@ public class InspectionProfileTest extends LightIdeaTestCase {
|
||||
profile.readExternal(element);
|
||||
final ModifiableModel model = profile.getModifiableModel();
|
||||
model.commit();
|
||||
final Element copy = new Element("inspections");
|
||||
profile.writeExternal(copy);
|
||||
assertElementsEqual(element, copy);
|
||||
assertElementsEqual(element, profile.writeExternal());
|
||||
}
|
||||
|
||||
private static InspectionProfileImpl createProfile() {
|
||||
@@ -146,49 +145,47 @@ public class InspectionProfileTest extends LightIdeaTestCase {
|
||||
ModifiableModel model = profile.getModifiableModel();
|
||||
model.commit();
|
||||
|
||||
Element copy = new Element("inspections");
|
||||
profile.writeExternal(copy);
|
||||
assertElementsEqual(loadProfile(), copy);
|
||||
assertElementsEqual(loadProfile(), profile.writeExternal());
|
||||
}
|
||||
|
||||
private static Element loadProfile() throws IOException, JDOMException {
|
||||
return JDOMUtil.loadDocument("<inspections version=\"1.0\">\n" +
|
||||
" <option name=\"myName\" value=\"ToConvert\" />\n" +
|
||||
" <inspection_tool class=\"JavaDoc\" enabled=\"false\" level=\"WARNING\" enabled_by_default=\"false\">\n" +
|
||||
" <option name=\"TOP_LEVEL_CLASS_OPTIONS\">\n" +
|
||||
" <value>\n" +
|
||||
" <option name=\"ACCESS_JAVADOC_REQUIRED_FOR\" value=\"none\" />\n" +
|
||||
" <option name=\"REQUIRED_TAGS\" value=\"\" />\n" +
|
||||
" </value>\n" +
|
||||
" </option>\n" +
|
||||
" <option name=\"INNER_CLASS_OPTIONS\">\n" +
|
||||
" <value>\n" +
|
||||
" <option name=\"ACCESS_JAVADOC_REQUIRED_FOR\" value=\"none\" />\n" +
|
||||
" <option name=\"REQUIRED_TAGS\" value=\"\" />\n" +
|
||||
" </value>\n" +
|
||||
" </option>\n" +
|
||||
" <option name=\"METHOD_OPTIONS\">\n" +
|
||||
" <value>\n" +
|
||||
" <option name=\"ACCESS_JAVADOC_REQUIRED_FOR\" value=\"none\" />\n" +
|
||||
" <option name=\"REQUIRED_TAGS\" value=\"@return@param@throws or @exception\" />\n" +
|
||||
" </value>\n" + " </option>\n" +
|
||||
" <option name=\"FIELD_OPTIONS\">\n" +
|
||||
" <value>\n" +
|
||||
" <option name=\"ACCESS_JAVADOC_REQUIRED_FOR\" value=\"none\" />\n" +
|
||||
" <option name=\"REQUIRED_TAGS\" value=\"\" />\n" +
|
||||
" </value>\n" +
|
||||
" </option>\n" +
|
||||
" <option name=\"IGNORE_DEPRECATED\" value=\"false\" />\n" +
|
||||
" <option name=\"IGNORE_JAVADOC_PERIOD\" value=\"false\" />\n" +
|
||||
" <option name=\"IGNORE_DUPLICATED_THROWS\" value=\"false\" />\n" +
|
||||
" <option name=\"IGNORE_POINT_TO_ITSELF\" value=\"false\" />\n" +
|
||||
" <option name=\"myAdditionalJavadocTags\" value=\"tag1,tag2 \" />\n" +
|
||||
" </inspection_tool>\n" +
|
||||
"</inspections>").getRootElement();
|
||||
return JdomKt.loadElement("<profile version=\"1.0\">\n" +
|
||||
" <option name=\"myName\" value=\"ToConvert\" />\n" +
|
||||
" <inspection_tool class=\"JavaDoc\" enabled=\"false\" level=\"WARNING\" enabled_by_default=\"false\">\n" +
|
||||
" <option name=\"TOP_LEVEL_CLASS_OPTIONS\">\n" +
|
||||
" <value>\n" +
|
||||
" <option name=\"ACCESS_JAVADOC_REQUIRED_FOR\" value=\"none\" />\n" +
|
||||
" <option name=\"REQUIRED_TAGS\" value=\"\" />\n" +
|
||||
" </value>\n" +
|
||||
" </option>\n" +
|
||||
" <option name=\"INNER_CLASS_OPTIONS\">\n" +
|
||||
" <value>\n" +
|
||||
" <option name=\"ACCESS_JAVADOC_REQUIRED_FOR\" value=\"none\" />\n" +
|
||||
" <option name=\"REQUIRED_TAGS\" value=\"\" />\n" +
|
||||
" </value>\n" +
|
||||
" </option>\n" +
|
||||
" <option name=\"METHOD_OPTIONS\">\n" +
|
||||
" <value>\n" +
|
||||
" <option name=\"ACCESS_JAVADOC_REQUIRED_FOR\" value=\"none\" />\n" +
|
||||
" <option name=\"REQUIRED_TAGS\" value=\"@return@param@throws or @exception\" />\n" +
|
||||
" </value>\n" + " </option>\n" +
|
||||
" <option name=\"FIELD_OPTIONS\">\n" +
|
||||
" <value>\n" +
|
||||
" <option name=\"ACCESS_JAVADOC_REQUIRED_FOR\" value=\"none\" />\n" +
|
||||
" <option name=\"REQUIRED_TAGS\" value=\"\" />\n" +
|
||||
" </value>\n" +
|
||||
" </option>\n" +
|
||||
" <option name=\"IGNORE_DEPRECATED\" value=\"false\" />\n" +
|
||||
" <option name=\"IGNORE_JAVADOC_PERIOD\" value=\"false\" />\n" +
|
||||
" <option name=\"IGNORE_DUPLICATED_THROWS\" value=\"false\" />\n" +
|
||||
" <option name=\"IGNORE_POINT_TO_ITSELF\" value=\"false\" />\n" +
|
||||
" <option name=\"myAdditionalJavadocTags\" value=\"tag1,tag2 \" />\n" +
|
||||
" </inspection_tool>\n" +
|
||||
"</profile>");
|
||||
}
|
||||
|
||||
public void testReloadProfileWithUnknownScopes() throws Exception {
|
||||
final Element element = JDOMUtil.loadDocument("<inspections version=\"1.0\">\n" +
|
||||
final Element element = JdomKt.loadElement("<profile version=\"1.0\">\n" +
|
||||
" <option name=\"myName\" value=\"" + PROFILE + "\" />\n" +
|
||||
" <inspection_tool class=\"ArgNamesErrorsInspection\" enabled=\"true\" level=\"ERROR\" enabled_by_default=\"false\" />\n" +
|
||||
" <inspection_tool class=\"ArgNamesWarningsInspection\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"false\" />\n" +
|
||||
@@ -199,32 +196,28 @@ public class InspectionProfileTest extends LightIdeaTestCase {
|
||||
" <inspection_tool class=\"UNUSED_IMPORT\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\">\n" +
|
||||
" <scope name=\"Unknown scope name\" level=\"WARNING\" enabled=\"true\" />\n" +
|
||||
" </inspection_tool>\n" +
|
||||
"</inspections>").getRootElement();
|
||||
"</profile>");
|
||||
final InspectionProfileImpl profile = createProfile();
|
||||
profile.readExternal(element);
|
||||
final ModifiableModel model = profile.getModifiableModel();
|
||||
model.commit();
|
||||
final Element copy = new Element("inspections");
|
||||
profile.writeExternal(copy);
|
||||
assertElementsEqual(element, copy);
|
||||
assertElementsEqual(element, profile.writeExternal());
|
||||
}
|
||||
|
||||
public void testMergeUnusedDeclarationAndUnusedSymbol() throws Exception {
|
||||
//no specific settings
|
||||
final Element element = JDOMUtil.loadDocument("<inspections version=\"1.0\">\n" +
|
||||
final Element element = JdomKt.loadElement("<profile version=\"1.0\">\n" +
|
||||
" <option name=\"myName\" value=\"" + PROFILE + "\" />\n" +
|
||||
"</inspections>").getRootElement();
|
||||
"</profile>");
|
||||
InspectionProfileImpl profile = createProfile(new InspectionProfileImpl("foo"));
|
||||
profile.readExternal(element);
|
||||
ModifiableModel model = profile.getModifiableModel();
|
||||
model.commit();
|
||||
final Element copy = new Element("inspections");
|
||||
profile.writeExternal(copy);
|
||||
assertElementsEqual(element, copy);
|
||||
assertElementsEqual(element, profile.writeExternal());
|
||||
|
||||
|
||||
//settings to merge
|
||||
final Element unusedProfile = JDOMUtil.loadDocument("<inspections version=\"1.0\">\n" +
|
||||
final Element unusedProfile = JdomKt.loadElement("<profile version=\"1.0\">\n" +
|
||||
" <option name=\"myName\" value=\"" + PROFILE + "\" />\n" +
|
||||
" <inspection_tool class=\"UNUSED_SYMBOL\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"false\">\n" +
|
||||
" <option name=\"LOCAL_VARIABLE\" value=\"true\" />\n" +
|
||||
@@ -240,7 +233,7 @@ public class InspectionProfileTest extends LightIdeaTestCase {
|
||||
" <option name=\"ADD_SERVLET_TO_ENTRIES\" value=\"true\" />\n" +
|
||||
" <option name=\"ADD_NONJAVA_TO_ENTRIES\" value=\"false\" />\n" +
|
||||
" </inspection_tool>\n" +
|
||||
"</inspections>").getRootElement();
|
||||
"</profile>");
|
||||
profile.readExternal(unusedProfile);
|
||||
model = profile.getModifiableModel();
|
||||
model.commit();
|
||||
@@ -292,8 +285,7 @@ public class InspectionProfileTest extends LightIdeaTestCase {
|
||||
"</profile>";
|
||||
assertEquals(mergedText, serialize(profile));
|
||||
|
||||
Element toImportElement = new Element("profile");
|
||||
profile.writeExternal(toImportElement);
|
||||
Element toImportElement = profile.writeExternal();
|
||||
final InspectionProfileImpl importedProfile =
|
||||
InspectionToolsConfigurable.importInspectionProfile(toImportElement, InspectionProfileManager.getInstance(), getProject(), null);
|
||||
|
||||
@@ -303,13 +295,9 @@ public class InspectionProfileTest extends LightIdeaTestCase {
|
||||
profile.readExternal(mergedElement);
|
||||
model = profile.getModifiableModel();
|
||||
model.commit();
|
||||
Element copyMerged = new Element("profile");
|
||||
profile.writeExternal(copyMerged);
|
||||
assertElementsEqual(mergedElement, copyMerged);
|
||||
assertElementsEqual(mergedElement, profile.writeExternal());
|
||||
|
||||
Element imported = new Element("profile");
|
||||
importedProfile.writeExternal(imported);
|
||||
assertElementsEqual(mergedElement, imported);
|
||||
assertElementsEqual(mergedElement, importedProfile.writeExternal());
|
||||
}
|
||||
|
||||
public void testDisabledUnusedDeclarationWithoutChanges() throws Exception {
|
||||
@@ -419,8 +407,7 @@ public class InspectionProfileTest extends LightIdeaTestCase {
|
||||
"</profile>",
|
||||
serialize(profile));
|
||||
|
||||
Element element = new Element("element");
|
||||
profile.writeExternal(element);
|
||||
Element element = profile.writeExternal();
|
||||
|
||||
list.add(createTool("bar", true));
|
||||
list.add(createTool("disabled", false));
|
||||
@@ -447,9 +434,7 @@ public class InspectionProfileTest extends LightIdeaTestCase {
|
||||
}
|
||||
|
||||
private static String serialize(InspectionProfileImpl profile) throws WriteExternalException {
|
||||
Element element = new Element("profile");
|
||||
profile.writeExternal(element);
|
||||
return JDOMUtil.writeElement(element);
|
||||
return JDOMUtil.writeElement(profile.writeExternal());
|
||||
}
|
||||
|
||||
private static InspectionProfileImpl createProfile(@NotNull InspectionToolRegistrar registrar) {
|
||||
@@ -508,7 +493,7 @@ public class InspectionProfileTest extends LightIdeaTestCase {
|
||||
profile.enableTool(id, getProject());
|
||||
}
|
||||
assertEquals(0, countInitializedTools(profile));
|
||||
profile.writeExternal(new Element("profile"));
|
||||
profile.writeExternal();
|
||||
List<InspectionToolWrapper> initializedTools = getInitializedTools(profile);
|
||||
if (initializedTools.size() > 0) {
|
||||
for (InspectionToolWrapper initializedTool : initializedTools) {
|
||||
@@ -543,9 +528,7 @@ public class InspectionProfileTest extends LightIdeaTestCase {
|
||||
"</profile>";
|
||||
foo.readExternal(JDOMUtil.loadDocument(test).getRootElement());
|
||||
foo.initInspectionTools(getProject());
|
||||
Element serialized = new Element("profile");
|
||||
foo.writeExternal(serialized);
|
||||
assertEquals(test, JDOMUtil.writeElement(serialized));
|
||||
assertEquals(test, JDOMUtil.writeElement(foo.writeExternal()));
|
||||
}
|
||||
|
||||
public static int countInitializedTools(Profile foo) {
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2000-2016 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.codeInspection.ex
|
||||
|
||||
import com.intellij.configurationStore.SchemeManagerFactoryBase
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.util.Computable
|
||||
import com.intellij.testFramework.ProjectRule
|
||||
import com.intellij.testFramework.TemporaryDirectory
|
||||
import com.intellij.util.readText
|
||||
import com.intellij.util.write
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.ClassRule
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
|
||||
internal class InspectionSchemeTest {
|
||||
companion object {
|
||||
@JvmField
|
||||
@ClassRule val projectRule = ProjectRule()
|
||||
}
|
||||
|
||||
private val tempDirManager = TemporaryDirectory()
|
||||
@Rule fun getTemporaryFolder() = tempDirManager
|
||||
|
||||
@Test fun loadSchemes() {
|
||||
val schemeDir = tempDirManager.newPath()
|
||||
val schemeFile = schemeDir.resolve("inspection/Bar.xml")
|
||||
val schemeData = """
|
||||
<inspections profile_name="Bar" version="1.0">
|
||||
<option name="myName" value="Bar" />
|
||||
<inspection_tool class="Since15" enabled="true" level="ERROR" enabled_by_default="true" />
|
||||
"</inspections>""".trimIndent()
|
||||
schemeFile.write(schemeData)
|
||||
val schemeManagerFactory = SchemeManagerFactoryBase.TestSchemeManagerFactory(schemeDir)
|
||||
val profileManager = InspectionProfileManagerImpl(InspectionToolRegistrar.getInstance(), schemeManagerFactory, ApplicationManager.getApplication().messageBus)
|
||||
profileManager.forceInitProfiles(true)
|
||||
profileManager.initProfiles()
|
||||
|
||||
assertThat(profileManager.profiles).hasSize(1)
|
||||
val scheme = profileManager.profiles.first() as InspectionProfileImpl
|
||||
assertThat(scheme.name).isEqualTo("Bar")
|
||||
|
||||
InspectionProfileImpl.initAndDo(Computable { scheme.initInspectionTools(null) })
|
||||
|
||||
schemeManagerFactory.save()
|
||||
|
||||
assertThat(schemeFile.readText()).isEqualTo(schemeData)
|
||||
profileManager.profiles
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
* Copyright 2000-2016 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.
|
||||
@@ -60,7 +60,7 @@ public abstract class DefaultProjectProfileManager extends ProjectProfileManager
|
||||
|
||||
private final ApplicationProfileManager myApplicationProfileManager;
|
||||
|
||||
private final Map<String, Profile> myProfiles = new THashMap<String, Profile>();
|
||||
private final Map<String, Profile> myProfiles = new THashMap<>();
|
||||
protected final DependencyValidationManager myHolder;
|
||||
private final List<ProfileChangeAdapter> myProfilesListener = ContainerUtil.createLockFreeCopyOnWriteList();
|
||||
@NonNls private static final String PROJECT_DEFAULT_PROFILE_NAME = "Project Default";
|
||||
@@ -101,8 +101,7 @@ public abstract class DefaultProjectProfileManager extends ProjectProfileManager
|
||||
for (String profile : sortedProfiles) {
|
||||
final Profile projectProfile = myProfiles.get(profile);
|
||||
if (projectProfile != null) {
|
||||
Element profileElement = new Element(PROFILE);
|
||||
projectProfile.writeExternal(profileElement);
|
||||
Element profileElement = projectProfile.writeExternal();
|
||||
boolean hasSmthToSave = sortedProfiles.length > 1 || isCustomProfileUsed();
|
||||
if (!hasSmthToSave) {
|
||||
for (Element child : profileElement.getChildren()) {
|
||||
|
||||
@@ -51,5 +51,12 @@ public interface Profile extends Comparable, Scheme {
|
||||
|
||||
void readExternal(Element element);
|
||||
|
||||
void writeExternal(Element element);
|
||||
default void writeExternal(Element element) {
|
||||
Element result = writeExternal();
|
||||
element.getAttributes().addAll(result.getAttributes());
|
||||
element.addContent(result.getContent());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
Element writeExternal();
|
||||
}
|
||||
|
||||
+18
-4
@@ -262,6 +262,17 @@ public class InspectionProfileImpl extends ProfileEx implements ModifiableModel,
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Element writeExternal() {
|
||||
if (myDataHolder == null) {
|
||||
return super.writeExternal();
|
||||
}
|
||||
else {
|
||||
return myDataHolder.read();
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Set<HighlightSeverity> getUsedSeverities() {
|
||||
LOG.assertTrue(myInitialized);
|
||||
@@ -565,7 +576,12 @@ public class InspectionProfileImpl extends ProfileEx implements ModifiableModel,
|
||||
for (InspectionToolWrapper toolWrapper : tools) {
|
||||
addTool(project, toolWrapper, dependencies);
|
||||
}
|
||||
final GraphGenerator<String> graphGenerator = GraphGenerator.create(CachingSemiGraph.create(new GraphGenerator.SemiGraph<String>() {
|
||||
|
||||
if (dataHolder != null) {
|
||||
dataHolder.updateDigest();
|
||||
}
|
||||
|
||||
DFSTBuilder<String> builder = new DFSTBuilder<>(GraphGenerator.create(CachingSemiGraph.create(new GraphGenerator.SemiGraph<String>() {
|
||||
@Override
|
||||
public Collection<String> getNodes() {
|
||||
return dependencies.keySet();
|
||||
@@ -575,9 +591,7 @@ public class InspectionProfileImpl extends ProfileEx implements ModifiableModel,
|
||||
public Iterator<String> getIn(String n) {
|
||||
return dependencies.get(n).iterator();
|
||||
}
|
||||
}));
|
||||
|
||||
DFSTBuilder<String> builder = new DFSTBuilder<>(graphGenerator);
|
||||
})));
|
||||
if (builder.isAcyclic()) {
|
||||
final List<String> scopes = builder.getSortedNodes();
|
||||
myScopesOrder = ArrayUtil.toStringArray(scopes);
|
||||
|
||||
@@ -61,11 +61,6 @@ public class InspectionToolRegistrar {
|
||||
if (!isInternal && ep.isInternal) continue;
|
||||
factories.add(() -> new GlobalInspectionToolWrapper(ep));
|
||||
}
|
||||
for (InspectionToolsFactory factory : Extensions.getExtensions(InspectionToolsFactory.EXTENSION_POINT_NAME)) {
|
||||
for (final InspectionProfileEntry profileEntry : factory.createTools()) {
|
||||
factories.add(() -> wrapTool(profileEntry));
|
||||
}
|
||||
}
|
||||
myInspectionToolFactories.addAll(factories);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
* Copyright 2000-2016 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.
|
||||
@@ -22,6 +22,8 @@ import com.intellij.util.xmlb.annotations.Transient;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import static com.intellij.profile.DefaultProjectProfileManager.PROFILE;
|
||||
|
||||
/**
|
||||
* User: anna
|
||||
* Date: 01-Dec-2005
|
||||
@@ -63,9 +65,7 @@ public abstract class ProfileEx implements Profile {
|
||||
|
||||
@Override
|
||||
public void copyFrom(@NotNull Profile profile) {
|
||||
Element config = new Element("config");
|
||||
profile.writeExternal(config);
|
||||
readExternal(config);
|
||||
readExternal(profile.writeExternal());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -116,9 +116,11 @@ public abstract class ProfileEx implements Profile {
|
||||
mySerializer.writeExternal(this, element, preserveCompatibility);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeExternal(Element element) {
|
||||
serializeInto(element, true);
|
||||
@NotNull
|
||||
public Element writeExternal() {
|
||||
Element result = new Element(PROFILE);
|
||||
serializeInto(result, true);
|
||||
return result;
|
||||
}
|
||||
|
||||
public void profileChanged() {
|
||||
|
||||
@@ -10,14 +10,10 @@ private enum class TypeMarker {
|
||||
ELEMENT, CDATA, TEXT, ELEMENT_END
|
||||
}
|
||||
|
||||
fun writeElement(element: Element, out: OutputStream) {
|
||||
fun serializeElementToBinary(element: Element, out: OutputStream) {
|
||||
writeElement(element, DataOutputStream(out))
|
||||
}
|
||||
|
||||
fun writeElement(element: Element, out: DataOutputStream) {
|
||||
writeElement(out, element)
|
||||
}
|
||||
|
||||
fun readElement(input: InputStream) = readElement(DataInputStream(input))
|
||||
|
||||
fun readElement(input: DataInputStream): Element {
|
||||
@@ -38,7 +34,7 @@ private fun readContent(element: Element, input: DataInputStream) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun writeElement(out: DataOutputStream, element: Element) {
|
||||
private fun writeElement(element: Element, out: DataOutputStream) {
|
||||
out.writeUTF(element.name)
|
||||
|
||||
writeAttributes(out, element.attributes)
|
||||
@@ -47,7 +43,7 @@ private fun writeElement(out: DataOutputStream, element: Element) {
|
||||
for (item in content) {
|
||||
if (item is Element) {
|
||||
out.writeByte(TypeMarker.ELEMENT.ordinal)
|
||||
writeElement(out, item)
|
||||
writeElement(item, out)
|
||||
}
|
||||
else if (item is Text) {
|
||||
if (!isAllWhitespace(item)) {
|
||||
|
||||
@@ -20,7 +20,6 @@ import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.components.ComponentManager
|
||||
import com.intellij.openapi.components.RoamingType
|
||||
import com.intellij.openapi.components.SettingsSavingComponent
|
||||
import com.intellij.openapi.components.impl.stores.StateStorageManager
|
||||
import com.intellij.openapi.components.stateStore
|
||||
import com.intellij.openapi.options.Scheme
|
||||
import com.intellij.openapi.options.SchemeManager
|
||||
@@ -30,6 +29,7 @@ import com.intellij.openapi.project.Project
|
||||
import com.intellij.util.SmartList
|
||||
import com.intellij.util.containers.ContainerUtil
|
||||
import com.intellij.util.lang.CompoundRuntimeException
|
||||
import org.jetbrains.annotations.TestOnly
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.Paths
|
||||
|
||||
@@ -38,13 +38,11 @@ const val ROOT_CONFIG = "\$ROOT_CONFIG$"
|
||||
sealed class SchemeManagerFactoryBase : SchemeManagerFactory(), SettingsSavingComponent {
|
||||
private val managers = ContainerUtil.createLockFreeCopyOnWriteList<SchemeManagerImpl<Scheme, out Scheme>>()
|
||||
|
||||
abstract val componentManager: ComponentManager
|
||||
protected open val componentManager: ComponentManager? = null
|
||||
|
||||
override final fun <T : Scheme, MutableT : T> create(directoryName: String, processor: SchemeProcessor<T, MutableT>, presentableName: String?, roamingType: RoamingType): SchemeManager<T> {
|
||||
val storageManager = (componentManager.stateStore).stateStorageManager
|
||||
|
||||
val path = checkPath(directoryName)
|
||||
val manager = SchemeManagerImpl(path, processor, (storageManager as? StateStorageManagerImpl)?.streamProvider, pathToFile(path, storageManager), roamingType, componentManager, presentableName)
|
||||
val manager = SchemeManagerImpl(path, processor, (componentManager?.stateStore?.stateStorageManager as? StateStorageManagerImpl)?.streamProvider, pathToFile(path), roamingType, componentManager, presentableName)
|
||||
@Suppress("CAST_NEVER_SUCCEEDS")
|
||||
managers.add(manager as SchemeManagerImpl<Scheme, out Scheme>)
|
||||
return manager
|
||||
@@ -63,7 +61,7 @@ sealed class SchemeManagerFactoryBase : SchemeManagerFactory(), SettingsSavingCo
|
||||
return originalPath
|
||||
}
|
||||
|
||||
abstract fun pathToFile(path: String, storageManager: StateStorageManager): Path
|
||||
abstract fun pathToFile(path: String): Path
|
||||
|
||||
fun process(processor: (SchemeManagerImpl<Scheme, out Scheme>) -> Unit) {
|
||||
for (manager in managers) {
|
||||
@@ -105,13 +103,18 @@ sealed class SchemeManagerFactoryBase : SchemeManagerFactory(), SettingsSavingCo
|
||||
return path
|
||||
}
|
||||
|
||||
override fun pathToFile(path: String, storageManager: StateStorageManager) = Paths.get(storageManager.expandMacros(ROOT_CONFIG), path)
|
||||
override fun pathToFile(path: String) = Paths.get(ApplicationManager.getApplication().stateStore.stateStorageManager.expandMacros(ROOT_CONFIG), path)
|
||||
}
|
||||
|
||||
@Suppress("unused")
|
||||
private class ProjectSchemeManagerFactory(private val project: Project) : SchemeManagerFactoryBase() {
|
||||
override val componentManager = project
|
||||
|
||||
override fun pathToFile(path: String, storageManager: StateStorageManager) = Paths.get(project.basePath, if (ProjectUtil.isDirectoryBased(project)) "${Project.DIRECTORY_STORE_FOLDER}/$path" else ".$path")
|
||||
override fun pathToFile(path: String) = Paths.get(project.basePath, if (ProjectUtil.isDirectoryBased(project)) "${Project.DIRECTORY_STORE_FOLDER}/$path" else ".$path")
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
class TestSchemeManagerFactory(private val basePath: Path) : SchemeManagerFactoryBase() {
|
||||
override fun pathToFile(path: String) = basePath.resolve(path)
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,7 @@ import com.intellij.openapi.project.ProjectBundle
|
||||
import com.intellij.openapi.util.Comparing
|
||||
import com.intellij.openapi.util.Condition
|
||||
import com.intellij.openapi.util.JDOMUtil
|
||||
import com.intellij.openapi.util.WriteExternalException
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.openapi.util.text.StringUtilRt
|
||||
import com.intellij.openapi.vfs.*
|
||||
@@ -48,7 +49,9 @@ import org.xmlpull.mxp1.MXParser
|
||||
import org.xmlpull.v1.XmlPullParser
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
import java.nio.file.Path
|
||||
import java.security.MessageDigest
|
||||
import java.util.*
|
||||
import java.util.function.Function
|
||||
|
||||
@@ -216,7 +219,7 @@ class SchemeManagerImpl<T : Scheme, MUTABLE_SCHEME : T>(val fileSpec: String,
|
||||
val fileName = PathUtilRt.getFileName(url.path)
|
||||
val extension = getFileExtension(fileName, true)
|
||||
val info = ExternalInfo(fileName.substring(0, fileName.length - extension.length), extension)
|
||||
info.hash = element.getTreeHash()
|
||||
info.digest = element.digest()
|
||||
info.schemeName = scheme.name
|
||||
val oldInfo = schemeToInfo.put(scheme, info)
|
||||
LOG.assertTrue(oldInfo == null)
|
||||
@@ -338,13 +341,24 @@ class SchemeManagerImpl<T : Scheme, MUTABLE_SCHEME : T>(val fileSpec: String,
|
||||
return info != null && schemeExtension != info.fileExtension
|
||||
}
|
||||
|
||||
private class SchemeDataHolderImpl(private val bytes: ByteArray, private val externalInfo: ExternalInfo) : SchemeDataHolder {
|
||||
override fun read(): Element {
|
||||
val element = loadElement(bytes.inputStream())
|
||||
if (externalInfo.hash == 0) {
|
||||
externalInfo.hash = element.getTreeHash()
|
||||
}
|
||||
return element
|
||||
private inner class SchemeDataHolderImpl(private val bytes: ByteArray, private val externalInfo: ExternalInfo) : SchemeDataHolder {
|
||||
override fun read() = loadElement(bytes.inputStream())
|
||||
|
||||
override fun updateDigest() {
|
||||
schemeToInfo.forEachEntry({ k, v ->
|
||||
if (v !== externalInfo) {
|
||||
return@forEachEntry true
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
try {
|
||||
externalInfo.digest = (processor.writeScheme(k as MUTABLE_SCHEME) as Element).digest()
|
||||
}
|
||||
catch (e: WriteExternalException) {
|
||||
LOG.error("Cannot update digest", e)
|
||||
}
|
||||
false
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -395,7 +409,7 @@ class SchemeManagerImpl<T : Scheme, MUTABLE_SCHEME : T>(val fileSpec: String,
|
||||
fun createInfo(schemeName: String, element: Element?): ExternalInfo {
|
||||
val info = ExternalInfo(fileNameWithoutExtension, extension)
|
||||
element?.let {
|
||||
info.hash = it.getTreeHash()
|
||||
info.digest = it.digest()
|
||||
}
|
||||
info.schemeName = schemeName
|
||||
return info
|
||||
@@ -558,14 +572,14 @@ class SchemeManagerImpl<T : Scheme, MUTABLE_SCHEME : T>(val fileSpec: String,
|
||||
fileNameWithoutExtension = nameGenerator.generateUniqueName(FileUtil.sanitizeFileName(scheme.name, false))
|
||||
}
|
||||
|
||||
val newHash = element!!.getTreeHash()
|
||||
if (externalInfo != null && currentFileNameWithoutExtension === fileNameWithoutExtension && newHash == externalInfo.hash) {
|
||||
val newDigest = element!!.digest()
|
||||
if (externalInfo != null && currentFileNameWithoutExtension === fileNameWithoutExtension && externalInfo.isDigestEquals(newDigest)) {
|
||||
return
|
||||
}
|
||||
|
||||
// save only if scheme differs from bundled
|
||||
val bundledScheme = readOnlyExternalizableSchemes.get(scheme.name)
|
||||
if (bundledScheme != null && schemeToInfo.get(bundledScheme)?.hash == newHash) {
|
||||
if (bundledScheme != null && schemeToInfo.get(bundledScheme)?.isDigestEquals(newDigest) ?: false) {
|
||||
externalInfo?.scheduleDelete()
|
||||
return
|
||||
}
|
||||
@@ -639,7 +653,7 @@ class SchemeManagerImpl<T : Scheme, MUTABLE_SCHEME : T>(val fileSpec: String,
|
||||
else {
|
||||
externalInfo.setFileNameWithoutExtension(fileNameWithoutExtension, schemeExtension)
|
||||
}
|
||||
externalInfo.hash = newHash
|
||||
externalInfo.digest = newDigest
|
||||
externalInfo.schemeName = scheme.name
|
||||
}
|
||||
|
||||
@@ -889,7 +903,8 @@ class SchemeManagerImpl<T : Scheme, MUTABLE_SCHEME : T>(val fileSpec: String,
|
||||
private class ExternalInfo(var fileNameWithoutExtension: String, var fileExtension: String?) {
|
||||
// we keep it to detect rename
|
||||
var schemeName: String? = null
|
||||
var hash = 0
|
||||
|
||||
var digest: ByteArray? = null
|
||||
|
||||
val fileName: String
|
||||
get() = "$fileNameWithoutExtension$fileExtension"
|
||||
@@ -899,6 +914,8 @@ class SchemeManagerImpl<T : Scheme, MUTABLE_SCHEME : T>(val fileSpec: String,
|
||||
fileExtension = extension
|
||||
}
|
||||
|
||||
fun isDigestEquals(newDigest: ByteArray) = Arrays.equals(digest, newDigest)
|
||||
|
||||
override fun toString() = fileName
|
||||
}
|
||||
|
||||
@@ -930,4 +947,25 @@ fun createDir(ioDir: Path, requestor: Any): VirtualFile {
|
||||
|
||||
fun getFile(fileName: String, parent: VirtualFile, requestor: Any): VirtualFile {
|
||||
return parent.findChild(fileName) ?: runWriteAction { parent.createChildData(requestor, fileName) }
|
||||
}
|
||||
|
||||
class DigestOutputStream(val digest: MessageDigest) : OutputStream() {
|
||||
override fun write(b: Int) {
|
||||
digest.update(b.toByte())
|
||||
}
|
||||
|
||||
override fun write(b: ByteArray, off: Int, len: Int) {
|
||||
digest.update(b, off, len)
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "[Digest Output Stream] " + digest.toString()
|
||||
}
|
||||
}
|
||||
|
||||
fun Element.digest(): ByteArray {
|
||||
// sha-1 is enough, sha-256 is slower, see https://www.nayuki.io/page/native-hash-functions-for-java
|
||||
val digest = MessageDigest.getInstance("SHA-1")
|
||||
serializeElementToBinary(this, DigestOutputStream(digest))
|
||||
return digest.digest()
|
||||
}
|
||||
@@ -32,7 +32,7 @@ import java.util.concurrent.atomic.AtomicReferenceArray
|
||||
fun archiveState(state: Element): BufferExposingByteArrayOutputStream {
|
||||
val byteOut = BufferExposingByteArrayOutputStream()
|
||||
SnappyOutputStream(byteOut).use {
|
||||
writeElement(state, it)
|
||||
serializeElementToBinary(state, it)
|
||||
}
|
||||
return byteOut
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ class BinaryXmlOutputterTest {
|
||||
private fun test(xml: String) {
|
||||
val byteOut = BufferExposingByteArrayOutputStream()
|
||||
byteOut.use {
|
||||
writeElement(loadElement(xml), it)
|
||||
serializeElementToBinary(loadElement(xml), it)
|
||||
}
|
||||
|
||||
val xmlAfter = JDOMUtil.writeElement(byteOut.toByteArray().inputStream().use { readElement(it) })
|
||||
|
||||
@@ -46,9 +46,13 @@ interface SchemeExtensionProvider {
|
||||
val isUpgradeNeeded: Boolean
|
||||
}
|
||||
|
||||
|
||||
interface SchemeDataHolder {
|
||||
/**
|
||||
* You should call updateDigest() after read on init.
|
||||
*/
|
||||
fun read(): Element
|
||||
|
||||
fun updateDigest()
|
||||
}
|
||||
|
||||
abstract class SchemeManagerFactory {
|
||||
|
||||
+1
-3
@@ -193,11 +193,9 @@ public class InspectionProfileManagerImpl extends InspectionProfileManager imple
|
||||
}
|
||||
|
||||
private void createDefaultProfile() {
|
||||
final InspectionProfileImpl defaultProfile = createSampleProfile(InspectionProfileImpl.DEFAULT_PROFILE_NAME, getDefaultProfile());
|
||||
addProfile(defaultProfile);
|
||||
addProfile(createSampleProfile(InspectionProfileImpl.DEFAULT_PROFILE_NAME, getDefaultProfile()));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Profile loadProfile(@NotNull String path) throws IOException, JDOMException {
|
||||
final File file = new File(path);
|
||||
|
||||
+2
-2
@@ -353,13 +353,13 @@ public abstract class InspectionToolsConfigurable extends BaseConfigurable
|
||||
final FileChooserDescriptor descriptor = FileChooserDescriptorFactory.createSingleFolderDescriptor();
|
||||
descriptor.setDescription("Choose directory to store profile file");
|
||||
FileChooser.chooseFile(descriptor, getProject(), wholePanel, null, file -> {
|
||||
final Element element = new Element("inspections");
|
||||
final Element element;
|
||||
try {
|
||||
final SingleInspectionProfilePanel panel = getSelectedPanel();
|
||||
LOG.assertTrue(panel != null);
|
||||
final InspectionProfileImpl profile = getSelectedObject();
|
||||
LOG.assertTrue(true);
|
||||
profile.writeExternal(element);
|
||||
element = profile.writeExternal();
|
||||
final String filePath =
|
||||
FileUtil.toSystemDependentName(file.getPath()) + File.separator + FileUtil.sanitizeFileName(profile.getName()) + ".xml";
|
||||
if (new File(filePath).isFile()) {
|
||||
|
||||
+5
-3
@@ -84,10 +84,12 @@ public class CodeStyleSchemeImpl implements CodeStyleScheme, ExternalizableSchem
|
||||
|
||||
@Override
|
||||
public CodeStyleSettings getCodeStyleSettings() {
|
||||
if (myDataHolder != null) {
|
||||
init(myParentSchemeName == null ? null : CodeStyleSchemesImpl.getSchemeManager().findSchemeByName(myParentSchemeName), myDataHolder.read());
|
||||
myParentSchemeName = null;
|
||||
SchemeDataHolder dataHolder = myDataHolder;
|
||||
if (dataHolder != null) {
|
||||
myDataHolder = null;
|
||||
init(myParentSchemeName == null ? null : CodeStyleSchemesImpl.getSchemeManager().findSchemeByName(myParentSchemeName), dataHolder.read());
|
||||
dataHolder.updateDigest();
|
||||
myParentSchemeName = null;
|
||||
}
|
||||
return myCodeStyleSettings;
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ public class CopyrightManager extends AbstractProjectComponent implements Persis
|
||||
}
|
||||
|
||||
@NonNls
|
||||
private static final String COPYRIGHT = "copyright";
|
||||
static final String COPYRIGHT = "copyright";
|
||||
@NonNls
|
||||
private static final String MODULE2COPYRIGHT = "module2copyright";
|
||||
@NonNls
|
||||
@@ -135,8 +135,7 @@ public class CopyrightManager extends AbstractProjectComponent implements Persis
|
||||
try {
|
||||
if (!myCopyrights.isEmpty()) {
|
||||
for (CopyrightProfile copyright : myCopyrights.values()) {
|
||||
Element copyrightElement = new Element(COPYRIGHT);
|
||||
copyright.writeExternal(copyrightElement);
|
||||
Element copyrightElement = copyright.writeExternal();
|
||||
if (!JDOMUtil.isEmpty(copyrightElement)) {
|
||||
state.addContent(copyrightElement);
|
||||
}
|
||||
@@ -291,7 +290,7 @@ public class CopyrightManager extends AbstractProjectComponent implements Persis
|
||||
@NotNull
|
||||
@Override
|
||||
protected String getSubStateTagName() {
|
||||
return "copyright";
|
||||
return COPYRIGHT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2016 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.
|
||||
@@ -18,6 +18,8 @@ package com.maddyhome.idea.copyright;
|
||||
import com.intellij.profile.ProfileEx;
|
||||
import com.intellij.util.xmlb.SmartSerializer;
|
||||
import com.maddyhome.idea.copyright.pattern.EntityUtil;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class CopyrightProfile extends ProfileEx {
|
||||
@SuppressWarnings("SpellCheckingInspection")
|
||||
@@ -64,4 +66,12 @@ public class CopyrightProfile extends ProfileEx {
|
||||
public void setAllowReplaceKeyword(String allowReplaceKeyword) {
|
||||
this.allowReplaceKeyword = allowReplaceKeyword;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Element writeExternal() {
|
||||
Element result = new Element(CopyrightManager.COPYRIGHT);
|
||||
serializeInto(result, true);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user