Cleanup build warnings, updated since-build, removed ModuleComponent. (#154)

* Cleanup build warnings, updated since-build, removed ModuleComponent.

* Refactor facet_basics for functionality/clarity. Incorporate feedback.

* Incorporate additional feedback.
This commit is contained in:
John Hake 2019-03-11 11:13:44 -07:00 committed by Yann Cébron
parent 0dca50d851
commit 4baf7c704e
23 changed files with 286 additions and 202 deletions

View File

@ -17,7 +17,7 @@ import java.util.StringTokenizer;
/** /**
* @author max * @author max
*/ */
public class ComparingReferencesInspection extends BaseJavaLocalInspectionTool { public class ComparingReferencesInspection extends AbstractBaseJavaLocalInspectionTool {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.ComparingReferencesInspection"); private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.ComparingReferencesInspection");
private final LocalQuickFix myQuickFix = new MyQuickFix(); private final LocalQuickFix myQuickFix = new MyQuickFix();

View File

@ -4,20 +4,27 @@ package testPlugin;
import com.intellij.codeInsight.daemon.impl.HighlightInfo; import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInspection.ComparingReferencesInspection; import com.intellij.codeInspection.ComparingReferencesInspection;
import com.intellij.codeInspection.InspectionToolProvider;
import com.intellij.testFramework.TestDataPath;
import com.intellij.testFramework.UsefulTestCase; import com.intellij.testFramework.UsefulTestCase;
import com.intellij.testFramework.builders.JavaModuleFixtureBuilder; import com.intellij.testFramework.builders.JavaModuleFixtureBuilder;
import com.intellij.testFramework.fixtures.*; import com.intellij.testFramework.fixtures.*;
import junit.framework.Assert; import org.junit.Assert;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
/** /**
* @see JavaCodeInsightFixtureTestCase * @see JavaCodeInsightFixtureTestCase
* @see LightCodeInsightFixtureTestCase * @see LightCodeInsightFixtureTestCase
*/ */
@TestDataPath("$CONTENT_ROOT/../testData")
public class TestThisPlugin extends UsefulTestCase { public class TestThisPlugin extends UsefulTestCase {
protected CodeInsightTestFixture myFixture; protected CodeInsightTestFixture myFixture;
// TODO: Get path to module root, then add path to testData
// Specify path to your test data directory // Specify path to your test data directory
// e.g. final String dataPath = "c:\\users\\john.doe\\idea\\community\\samples\\ComparingReferences/testData"; // e.g. final String dataPath = "c:\\users\\john.doe\\idea\\community\\samples\\ComparingReferences/testData";
final String dataPath = "c:\\users\\John.Doe\\idea\\community\\samples\\comparingReferences/testData"; final String dataPath = "c:\\users\\John.Doe\\idea\\community\\samples\\comparingReferences/testData";
@ -44,6 +51,7 @@ public class TestThisPlugin extends UsefulTestCase {
protected void doTest(String testName, String hint) throws Throwable { protected void doTest(String testName, String hint) throws Throwable {
myFixture.configureByFile(testName + ".java"); myFixture.configureByFile(testName + ".java");
myFixture.enableInspections(ComparingReferencesInspection.class); myFixture.enableInspections(ComparingReferencesInspection.class);
List<HighlightInfo> highlightInfos = myFixture.doHighlighting(); List<HighlightInfo> highlightInfos = myFixture.doHighlighting();
Assert.assertTrue(!highlightInfos.isEmpty()); Assert.assertTrue(!highlightInfos.isEmpty());

View File

@ -1,14 +1,37 @@
<!-- Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
<idea-plugin> <idea-plugin>
<id>com.intellij.tutorials.facet</id>
<name>Facet Demo</name>
<version>1.0</version>
<vendor>JetBrains</vendor>
<description>Basic example of adding support for custom Facets</description> <!-- Unique id for this plugin. Must stay constant for the life of the plugin. -->
<id>org.intellij.sdk.facet</id>
<idea-version since-build="131"/> <!-- Text to display as name on Preferences/Settings | Plugin page -->
<name>SDK Facet Basics</name>
<!-- Text to display as description on Preferences/Settings | Plugin page -->
<description>
<![CDATA[
Demonstrates implementing the custom Facet pattern.<br>Adds <em>SDK Facet</em> to the Project Structure | Project Settings | Facets menu.
]]>
</description>
<change-notes>
<![CDATA[
<b>2.0</b> Refactored to illustrate use of PersistentComponent.<br>
<b>1.0</b> Release 2018.3 and earlier.
]]>
</change-notes>
<!-- Text to display as company information on Preferences/Settings | Plugin page -->
<vendor email="sdk-example@jetbrains.com" url="https://plugins.jetbrains.com">IntelliJ Platform SDK</vendor>
<!-- The version of this plugin -->
<version>2.0</version>
<!-- Compatible with the following versions of IntelliJ Platform -->
<idea-version since-build="173"/>
<extensions defaultExtensionNs="com.intellij"> <extensions defaultExtensionNs="com.intellij">
<!-- Register the custom facet extension -->
<facetType implementation="com.intellij.tutorials.facet.DemoFacetType"/> <facetType implementation="com.intellij.tutorials.facet.DemoFacetType"/>
</extensions> </extensions>

View File

@ -1,13 +1,16 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.tutorials.facet; package com.intellij.tutorials.facet;
import com.intellij.facet.*; import com.intellij.facet.Facet;
import com.intellij.facet.FacetType;
import com.intellij.openapi.module.Module; import com.intellij.openapi.module.Module;
/** /**
* Demo Facet class. Everything is handled by the super class.
* @author Anna Bulenkova * @author Anna Bulenkova
*/ */
public class DemoFacet extends Facet<DemoFacetConfiguration> { public class DemoFacet extends Facet<DemoFacetConfiguration> {
public static final String ID = "DEMO_FACET_ID";
public DemoFacet(FacetType facetType, public DemoFacet(FacetType facetType,
Module module, Module module,
@ -16,4 +19,5 @@ public class DemoFacet extends Facet<DemoFacetConfiguration> {
Facet underlyingFacet) { Facet underlyingFacet) {
super(facetType, module, name, configuration, underlyingFacet); super(facetType, module, name, configuration, underlyingFacet);
} }
} }

View File

@ -1,76 +1,61 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.tutorials.facet; package com.intellij.tutorials.facet;
import com.intellij.facet.FacetConfiguration; import com.intellij.facet.FacetConfiguration;
import com.intellij.facet.ui.*; import com.intellij.facet.ui.FacetEditorContext;
import com.intellij.openapi.util.*; import com.intellij.facet.ui.FacetEditorTab;
import org.jdom.Element; import com.intellij.facet.ui.FacetValidatorsManager;
import org.jetbrains.annotations.*; import com.intellij.openapi.components.PersistentStateComponent;
import org.jetbrains.annotations.NotNull;
import javax.swing.*; import org.jetbrains.annotations.Nullable;
import java.awt.*;
/** /**
* Provides a custom implementation of the Configuration class for DemoFacet.
*
* @author Anna Bulenkova * @author Anna Bulenkova
* @author John Hake
*/ */
public class DemoFacetConfiguration implements FacetConfiguration { public class DemoFacetConfiguration implements FacetConfiguration, PersistentStateComponent<DemoFacetState> {
public static final String DEMO_FACET_TAG_NAME = "DemoFacet";
public static final String PATH_TO_SDK_ATTR_NAME = "pathToSdk";
private String myPathToSdk = "";
JTextField myPath = new JTextField(myPathToSdk);
// Manages the data stored with this facet.
private DemoFacetState myFacetState = new DemoFacetState();
/**
* Called by the IntelliJ Platform when saving this facet's state persistently.
* @return a component state. All properties, public and annotated fields are serialized.
* Only values which differ from default (i.e. the value of newly instantiated class) are serialized.
* {@code null} value indicates that the returned state won't be stored, and
* as a result previously stored state will be used.
*/
@Nullable
@Override
public DemoFacetState getState() {
return myFacetState;
}
/**
* Called by the IntelliJ Platform when this facet's state is loaded.
* The method can and will be called several times, if
* config files were externally changed while IDEA running.
*/
@Override
public void loadState(@NotNull DemoFacetState state) {
myFacetState = state;
}
/**
* Creates a set of editor tabs for this facet, potentially one per context.
*
* @param context The context in which a facet is being added/deleted, or modified.
* @param manager The manager which can be used to access custom validators.
* @return Array of DemoFacetEditorTabs. In this case size is always 1.
*/
@Override @Override
public FacetEditorTab[] createEditorTabs(FacetEditorContext context, FacetValidatorsManager manager) { public FacetEditorTab[] createEditorTabs(FacetEditorContext context, FacetValidatorsManager manager) {
return new FacetEditorTab[]{ return new FacetEditorTab[]{
new FacetEditorTab() { new DemoFacetEditorTab(myFacetState, context, manager)
@NotNull
@Override
public JComponent createComponent() {
JPanel top = new JPanel(new BorderLayout());
top.add(new JLabel("Path to SDK: "), BorderLayout.WEST);
top.add(myPath);
JPanel panel = new JPanel(new BorderLayout());
panel.add(top, BorderLayout.NORTH);
return panel;
}
@Nls
@Override
public String getDisplayName() {
return "Demo Framework";
}
@Override
public boolean isModified() {
return myPath.getText().equalsIgnoreCase(myPathToSdk);
// return !StringUtil.equalsIgnoreWhitespaces(myPath.getText(), myPathToSdk);
}
@Override
public void reset() {
myPath.setText(myPathToSdk);
}
@Override
public void disposeUIResources() {
}
}
}; };
} }
@Override
public void readExternal(Element element) throws InvalidDataException {
Element facet = element.getChild(DEMO_FACET_TAG_NAME);
if (facet != null) {
myPathToSdk = facet.getAttributeValue(PATH_TO_SDK_ATTR_NAME, "");
myPath.setText(myPathToSdk);
}
}
@Override
public void writeExternal(Element element) throws WriteExternalException {
Element facet = new Element(DEMO_FACET_TAG_NAME);
facet.setAttribute(PATH_TO_SDK_ATTR_NAME, myPathToSdk);
element.addContent(facet);
}
} }

View File

@ -0,0 +1,107 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.tutorials.facet;
import com.intellij.facet.ui.FacetEditorContext;
import com.intellij.facet.ui.FacetEditorTab;
import com.intellij.facet.ui.FacetValidatorsManager;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.util.Comparing;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
/**
* Provides the JPanel to be displayed in the facet UI.
* Manages validation and modification of the DemoFacet state.
*
* @author John Hake
*/
public class DemoFacetEditorTab extends FacetEditorTab {
private static final String FACET_PANEL_PROMPT = "Path To SDK: ";
private final DemoFacetState mySettings;
private final JTextField myPath;
/**
* Only DemoFacetState is captured so it can be updated per user changes
* in the EditorTab.
*
* @param state DemoFacetState object persisting DemoFacet state.
* @param context Facet editor context, can be used to get e.g. the current project module.
* @param validator Facet validator manager, can be used to get and apply a custom validator for
* this facet.
*/
public DemoFacetEditorTab(@NotNull DemoFacetState state, @NotNull FacetEditorContext context, @NotNull FacetValidatorsManager validator) {
mySettings = state;
myPath = new JTextField(state.getDemoFacetState());
}
/**
* Provides the JPanel displayed in the Preferences | Facet UI
*
* @return JPanel to be displayed in the DemoFacetEditorTab.
*/
@NotNull
@Override
public JComponent createComponent() {
JPanel top = new JPanel(new BorderLayout());
top.add(new JLabel(FACET_PANEL_PROMPT), BorderLayout.WEST);
top.add(myPath);
JPanel facetPanel = new JPanel(new BorderLayout());
facetPanel.add(top, BorderLayout.NORTH);
return facetPanel;
}
/**
* @return the name of this facet for display in this editor tab.
*/
@Override
@Nls(capitalization = Nls.Capitalization.Title)
public String getDisplayName() {
return DemoFacetType.FACET_NAME;
}
/**
* Determines if the facet state entered in the UI differs
* from the currently stored state.
* Called when user changes text in myPath.
*
* @return {@code true} if the state returned from the panel's UI
* differs from the stored facet state.
*/
@Override
public boolean isModified() {
boolean foo = !Comparing.equal(mySettings.getDemoFacetState(), myPath.getText().trim());
return foo;
}
/**
* Stores new facet state (text) entered by the user.
* Called when {@link #isModified()} returns true.
* @throws ConfigurationException if anything generates an exception.
*/
@Override
public void apply() throws ConfigurationException {
// Not much to go wrong here, but fulfill the contract
try {
String newTextContent = myPath.getText();
mySettings.setDemoFacetState(newTextContent);
} catch(Exception e) {
throw new ConfigurationException(e.toString());
}
}
/**
* Copies current DemoFacetState into the myPath UI element.
* This method is called each time this editor tab is needed for display.
*/
@Override
public void reset() {
myPath.setText(mySettings.getDemoFacetState());
}
}

View File

@ -0,0 +1,32 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.tutorials.facet;
import org.jetbrains.annotations.NotNull;
/**
* A simple class to store state for the DemoFacet.
* In this case it is just a string containing a path to an SDK.
*
* @author John Hake
*/
public class DemoFacetState {
static final String DEMO_FACET_INIT_PATH = "";
public String myPathToSdk;
DemoFacetState() {
setDemoFacetState(DEMO_FACET_INIT_PATH);
}
@NotNull
public String getDemoFacetState() {
return myPathToSdk;
}
public void setDemoFacetState(@NotNull String newPath) {
myPathToSdk = newPath;
}
}

View File

@ -1,3 +1,5 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.tutorials.facet; package com.intellij.tutorials.facet;
import com.intellij.facet.*; import com.intellij.facet.*;
@ -8,13 +10,19 @@ import org.jetbrains.annotations.*;
import javax.swing.*; import javax.swing.*;
/** /**
* Defines the type, id, and name of the DemoFacet. Provides creation of DemoFacet
* and associated Configuration.
* Allows application of this facet to all ModuleTypes.
*
* @author Anna Bulenkova * @author Anna Bulenkova
*/ */
public class DemoFacetType extends FacetType<DemoFacet, DemoFacetConfiguration> { public class DemoFacetType extends FacetType<DemoFacet, DemoFacetConfiguration> {
private static final FacetTypeId<DemoFacet> TYPE_ID = new FacetTypeId<DemoFacet>(DemoFacet.ID); public static final String FACET_ID = "DEMO_FACET_ID";
public static final String FACET_NAME = "SDK Facet";
public static final FacetTypeId<DemoFacet> DEMO_FACET_TYPE_ID = new FacetTypeId<DemoFacet>(FACET_ID);
public DemoFacetType() { public DemoFacetType() {
super(TYPE_ID, DemoFacet.ID, "Demo Facet"); super(DEMO_FACET_TYPE_ID, FACET_ID, FACET_NAME);
} }
@Override @Override
@ -31,7 +39,7 @@ public class DemoFacetType extends FacetType<DemoFacet, DemoFacetConfiguration>
} }
@Override @Override
public boolean isSuitableModuleType(ModuleType type) { public boolean isSuitableModuleType(final ModuleType type) {
return true; return true;
} }

View File

@ -58,14 +58,6 @@
</component> </component>
</project-components> </project-components>
<!-- Plugin's module components -->
<module-components>
<component>
<interface-class>org.jetbrains.tutorials.sample.DummyModuleComponent</interface-class>
<implementation-class>org.jetbrains.tutorials.sample.DummyModuleComponentImpl</implementation-class>
</component>
</module-components>
<!-- Actions --> <!-- Actions -->
<actions> <actions>
<!-- The <action> element defines an action to register. <!-- The <action> element defines an action to register.

View File

@ -1,9 +1,9 @@
package org.jetbrains.tutorials.sample; package org.jetbrains.tutorials.sample;
import com.intellij.openapi.components.ApplicationComponent; import com.intellij.openapi.components.BaseComponent;
/** /**
* @author Anna Bulenkova * @author Anna Bulenkova
*/ */
interface DummyApplicationComponent extends ApplicationComponent { interface DummyApplicationComponent extends BaseComponent {
} }

View File

@ -1,9 +0,0 @@
package org.jetbrains.tutorials.sample;
import com.intellij.openapi.module.ModuleComponent;
/**
* @author Anna Bulenkova
*/
public interface DummyModuleComponent extends ModuleComponent {
}

View File

@ -1,39 +0,0 @@
package org.jetbrains.tutorials.sample;
import org.jetbrains.annotations.NotNull;
/**
* @author Anna Bulenkova
*/
public class DummyModuleComponentImpl implements DummyModuleComponent {
@Override
public void projectOpened() {
}
@Override
public void projectClosed() {
}
@Override
public void moduleAdded() {
}
@Override
public void initComponent() {
}
@Override
public void disposeComponent() {
}
@NotNull
@Override
public String getComponentName() {
return "DummyModuleComponent";
}
}

View File

@ -6,7 +6,7 @@
<description>Project View Pane Demo listing only image files</description> <description>Project View Pane Demo listing only image files</description>
<idea-version since-build="131"/> <idea-version since-build="172.2103.15"/>
<depends>com.intellij.modules.lang</depends> <depends>com.intellij.modules.lang</depends>
<extensions defaultExtensionNs="com.intellij"> <extensions defaultExtensionNs="com.intellij">

View File

@ -7,6 +7,7 @@ import com.intellij.ide.util.treeView.AbstractTreeNode;
import com.intellij.openapi.Disposable; import com.intellij.openapi.Disposable;
import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectUtil;
import com.intellij.openapi.util.*; import com.intellij.openapi.util.*;
import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.*; import com.intellij.openapi.vfs.*;
@ -24,7 +25,7 @@ public class ImagesProjectNode extends AbstractTreeNode<VirtualFile> {
private static final Key<Set<VirtualFile>> IMAGES_PROJECT_DIRS = Key.create("images.files.or.directories"); private static final Key<Set<VirtualFile>> IMAGES_PROJECT_DIRS = Key.create("images.files.or.directories");
public ImagesProjectNode(final Project project) { public ImagesProjectNode(final Project project) {
super(project, project.getBaseDir()); super(project, ProjectUtil.guessProjectDir(project));
scanImages(project); scanImages(project);
subscribeToVFS(project); subscribeToVFS(project);
@ -37,11 +38,12 @@ public class ImagesProjectNode extends AbstractTreeNode<VirtualFile> {
private void scanImages(Project project) { private void scanImages(Project project) {
addAllByExt(project, "png"); addAllByExt(project, "png");
addAllByExt(project, "jpg"); addAllByExt(project, "jpg");
addAllByExt(project, "svg");
} }
private void addAllByExt(Project project, String ext) { private void addAllByExt(Project project, String ext) {
final Set<VirtualFile> imagesFiles = getImagesFiles(project); final Set<VirtualFile> imagesFiles = getImagesFiles(project);
final VirtualFile projectDir = project.getBaseDir(); final VirtualFile projectDir = ProjectUtil.guessProjectDir(project);
for (VirtualFile file : FilenameIndex.getAllFilesByExt(project, ext)) { for (VirtualFile file : FilenameIndex.getAllFilesByExt(project, ext)) {
while (file != null && !file.equals(projectDir)) { while (file != null && !file.equals(projectDir)) {
imagesFiles.add(file); imagesFiles.add(file);
@ -76,7 +78,7 @@ public class ImagesProjectNode extends AbstractTreeNode<VirtualFile> {
} }
if (files.isEmpty()) return Collections.emptyList(); if (files.isEmpty()) return Collections.emptyList();
final List<AbstractTreeNode> nodes = new ArrayList<AbstractTreeNode>(files.size()); final List<AbstractTreeNode> nodes = new ArrayList<AbstractTreeNode>(files.size());
final boolean alwaysOnTop = ((ProjectViewImpl) ProjectView.getInstance(myProject)).isFoldersAlwaysOnTop(); final boolean alwaysOnTop = ((ProjectViewImpl) ProjectView.getInstance(myProject)).isFoldersAlwaysOnTop("");
Collections.sort(files, new Comparator<VirtualFile>() { Collections.sort(files, new Comparator<VirtualFile>() {
@Override @Override
public int compare(VirtualFile o1, VirtualFile o2) { public int compare(VirtualFile o1, VirtualFile o2) {
@ -120,9 +122,9 @@ public class ImagesProjectNode extends AbstractTreeNode<VirtualFile> {
private void subscribeToVFS(final Project project) { private void subscribeToVFS(final Project project) {
final Alarm alarm = new Alarm(Alarm.ThreadToUse.POOLED_THREAD, project); final Alarm alarm = new Alarm(Alarm.ThreadToUse.POOLED_THREAD, project);
LocalFileSystem.getInstance().addVirtualFileListener(new VirtualFileAdapter() { LocalFileSystem.getInstance().addVirtualFileListener(new VirtualFileListener() {
{ {
final VirtualFileAdapter me = this; final VirtualFileListener me = this;
Disposer.register(project, new Disposable() { Disposer.register(project, new Disposable() {
@Override @Override
public void dispose() { public void dispose() {

View File

@ -23,7 +23,7 @@ public class ImagesProjectViewPane extends AbstractProjectViewPSIPane {
@Override @Override
public String getTitle() { public String getTitle() {
return "Images"; return "SDK-Images";
} }
@Override @Override
@ -82,11 +82,6 @@ public class ImagesProjectViewPane extends AbstractProjectViewPSIPane {
@Override @Override
protected ProjectViewTree createTree(DefaultTreeModel model) { protected ProjectViewTree createTree(DefaultTreeModel model) {
return new ProjectViewTree(myProject, model) { return new ProjectViewTree(myProject, model) {
@Override
public DefaultMutableTreeNode getSelectedNode() {
return ImagesProjectViewPane.this.getSelectedNode();
}
@Override @Override
public boolean isRootVisible() { public boolean isRootVisible() {
return true; return true;

View File

@ -7,7 +7,7 @@
<description><![CDATA[Simple language plugin for <description><![CDATA[Simple language plugin for
<a href="http://www.jetbrains.org/intellij/sdk/docs/tutorials/custom_language_support_tutorial.html">Custom Language Support Tutorial</a>]]></description> <a href="http://www.jetbrains.org/intellij/sdk/docs/tutorials/custom_language_support_tutorial.html">Custom Language Support Tutorial</a>]]></description>
<idea-version since-build="107.105"/> <idea-version since-build="183.3283.2"/>
<extensions defaultExtensionNs="com.intellij"> <extensions defaultExtensionNs="com.intellij">
<fileTypeFactory implementation="com.simpleplugin.SimpleFileTypeFactory"/> <fileTypeFactory implementation="com.simpleplugin.SimpleFileTypeFactory"/>

View File

@ -10,6 +10,7 @@ import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory; import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectUtil;
import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.Navigatable; import com.intellij.pom.Navigatable;
import com.intellij.psi.PsiFile; import com.intellij.psi.PsiFile;
@ -56,14 +57,13 @@ class CreatePropertyQuickFix extends BaseIntentionAction {
@Override @Override
public void run() { public void run() {
Collection<VirtualFile> virtualFiles = Collection<VirtualFile> virtualFiles =
FileBasedIndex.getInstance().getContainingFiles(FileTypeIndex.NAME, SimpleFileType.INSTANCE, FileTypeIndex.getFiles(SimpleFileType.INSTANCE, GlobalSearchScope.allScope(project) );
GlobalSearchScope.allScope(project));
if (virtualFiles.size() == 1) { if (virtualFiles.size() == 1) {
createProperty(project, virtualFiles.iterator().next()); createProperty(project, virtualFiles.iterator().next());
} else { } else {
final FileChooserDescriptor descriptor = final FileChooserDescriptor descriptor =
FileChooserDescriptorFactory.createSingleFileDescriptor(SimpleFileType.INSTANCE); FileChooserDescriptorFactory.createSingleFileDescriptor(SimpleFileType.INSTANCE);
descriptor.setRoots(project.getBaseDir()); descriptor.setRoots(ProjectUtil.guessProjectDir(project));
final VirtualFile file = FileChooser.chooseFile(descriptor, project, null); final VirtualFile file = FileChooser.chooseFile(descriptor, project, null);
if (file != null) { if (file != null) {
createProperty(project, file); createProperty(project, file);
@ -74,29 +74,18 @@ class CreatePropertyQuickFix extends BaseIntentionAction {
} }
private void createProperty(final Project project, final VirtualFile file) { private void createProperty(final Project project, final VirtualFile file) {
new WriteCommandAction.Simple(project) { WriteCommandAction.writeCommandAction(project).run(() -> {
@Override SimpleFile simpleFile = (SimpleFile) PsiManager.getInstance(project).findFile(file);
public void run() { ASTNode lastChildNode = simpleFile.getNode().getLastChildNode();
SimpleFile simpleFile = (SimpleFile) PsiManager.getInstance(project).findFile(file); // TODO: Add another check for CRLF
ASTNode lastChildNode = simpleFile.getNode().getLastChildNode(); if (lastChildNode != null/* && !lastChildNode.getElementType().equals(SimpleTypes.CRLF)*/) {
// TODO: Add another check for CRLF simpleFile.getNode().addChild(SimpleElementFactory.createCRLF(project).getNode());
if (lastChildNode != null/* && !lastChildNode.getElementType().equals(SimpleTypes.CRLF)*/) {
simpleFile.getNode().addChild(SimpleElementFactory.createCRLF(project).getNode());
}
// IMPORTANT: change spaces to escaped spaces or the new node will only have the first word for the key
SimpleProperty property = SimpleElementFactory.createProperty(project, key.replaceAll(" ", "\\\\ "), "");
simpleFile.getNode().addChild(property.getNode());
((Navigatable) property.getLastChild().getNavigationElement()).navigate(true);
FileEditorManager.getInstance(project).getSelectedTextEditor().getCaretModel().
moveCaretRelatively(2, 0, false, false, false);
// almost the same thing but manipulating plain text of the document instead of PSI
// FileEditorManager.getInstance(project).openFile(file, true);
// final Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor();
// final Document document = editor.getDocument();
// document.insertString(document.getTextLength(), "\n" + key.replaceAll(" ", "\\\\ ") + " = ");
// editor.getCaretModel().getPrimaryCaret().moveToOffset(document.getTextLength());
} }
}.execute(); // IMPORTANT: change spaces to escaped spaces or the new node will only have the first word for the key
SimpleProperty property = SimpleElementFactory.createProperty(project, key.replaceAll(" ", "\\\\ "), "");
simpleFile.getNode().addChild(property.getNode());
((Navigatable) property.getLastChild().getNavigationElement()).navigate(true);
FileEditorManager.getInstance(project).getSelectedTextEditor().getCaretModel().moveCaretRelatively(2, 0, false, false, false);
});
} }
} }

View File

@ -17,20 +17,14 @@ public class SimpleCodeStyleSettingsProvider extends CodeStyleSettingsProvider {
return "Simple"; return "Simple";
} }
@NotNull @NotNull
@Override public CodeStyleConfigurable createConfigurable(@NotNull CodeStyleSettings settings, @NotNull CodeStyleSettings modelSettings) {
public Configurable createSettingsPage(CodeStyleSettings settings, CodeStyleSettings originalSettings) { return new CodeStyleAbstractConfigurable(settings, modelSettings, this.getConfigurableDisplayName()) {
return new CodeStyleAbstractConfigurable(settings, originalSettings, "Simple") {
@Override @Override
protected CodeStyleAbstractPanel createPanel(CodeStyleSettings settings) { protected CodeStyleAbstractPanel createPanel(CodeStyleSettings settings) {
return new SimpleCodeStyleMainPanel(getCurrentSettings(), settings); return new SimpleCodeStyleMainPanel(getCurrentSettings(), settings);
} }
@Nullable
@Override
public String getHelpTopic() {
return null;
}
}; };
} }

View File

@ -24,7 +24,7 @@ public class SimpleFormattingModelBuilder implements FormattingModelBuilder {
private static SpacingBuilder createSpaceBuilder(CodeStyleSettings settings) { private static SpacingBuilder createSpaceBuilder(CodeStyleSettings settings) {
return new SpacingBuilder(settings, SimpleLanguage.INSTANCE) return new SpacingBuilder(settings, SimpleLanguage.INSTANCE)
.around(SimpleTypes.SEPARATOR) .around(SimpleTypes.SEPARATOR)
.spaceIf(settings.SPACE_AROUND_ASSIGNMENT_OPERATORS) .spaceIf(settings.getCommonSettings(SimpleLanguage.INSTANCE.getID()).SPACE_AROUND_ASSIGNMENT_OPERATORS)
.before(SimpleTypes.PROPERTY) .before(SimpleTypes.PROPERTY)
.none(); .none();
} }

View File

@ -50,7 +50,7 @@ public class SimpleParserDefinition implements ParserDefinition {
return new SimpleFile(viewProvider); return new SimpleFile(viewProvider);
} }
public SpaceRequirements spaceExistanceTypeBetweenTokens(ASTNode left, ASTNode right) { public SpaceRequirements spaceExistenceTypeBetweenTokens(ASTNode left, ASTNode right) {
return SpaceRequirements.MAY; return SpaceRequirements.MAY;
} }

View File

@ -14,8 +14,7 @@ public class SimpleUtil {
public static List<SimpleProperty> findProperties(Project project, String key) { public static List<SimpleProperty> findProperties(Project project, String key) {
List<SimpleProperty> result = null; List<SimpleProperty> result = null;
Collection<VirtualFile> virtualFiles = Collection<VirtualFile> virtualFiles =
FileBasedIndex.getInstance().getContainingFiles(FileTypeIndex.NAME, SimpleFileType.INSTANCE, FileTypeIndex.getFiles(SimpleFileType.INSTANCE, GlobalSearchScope.allScope(project));
GlobalSearchScope.allScope(project));
for (VirtualFile virtualFile : virtualFiles) { for (VirtualFile virtualFile : virtualFiles) {
SimpleFile simpleFile = (SimpleFile) PsiManager.getInstance(project).findFile(virtualFile); SimpleFile simpleFile = (SimpleFile) PsiManager.getInstance(project).findFile(virtualFile);
if (simpleFile != null) { if (simpleFile != null) {
@ -38,8 +37,7 @@ public class SimpleUtil {
public static List<SimpleProperty> findProperties(Project project) { public static List<SimpleProperty> findProperties(Project project) {
List<SimpleProperty> result = new ArrayList<SimpleProperty>(); List<SimpleProperty> result = new ArrayList<SimpleProperty>();
Collection<VirtualFile> virtualFiles = Collection<VirtualFile> virtualFiles =
FileBasedIndex.getInstance().getContainingFiles(FileTypeIndex.NAME, SimpleFileType.INSTANCE, FileTypeIndex.getFiles(SimpleFileType.INSTANCE, GlobalSearchScope.allScope(project));
GlobalSearchScope.allScope(project));
for (VirtualFile virtualFile : virtualFiles) { for (VirtualFile virtualFile : virtualFiles) {
SimpleFile simpleFile = (SimpleFile) PsiManager.getInstance(project).findFile(virtualFile); SimpleFile simpleFile = (SimpleFile) PsiManager.getInstance(project).findFile(virtualFile);
if (simpleFile != null) { if (simpleFile != null) {

View File

@ -1,11 +1,11 @@
package com.simpleplugin; package com.simpleplugin;
import com.intellij.application.options.CodeStyle;
import com.intellij.codeInsight.completion.CompletionType; import com.intellij.codeInsight.completion.CompletionType;
import com.intellij.codeInsight.generation.actions.CommentByLineCommentAction; import com.intellij.codeInsight.generation.actions.CommentByLineCommentAction;
import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
import com.intellij.usageView.UsageInfo; import com.intellij.usageView.UsageInfo;
import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.ContainerUtil;
@ -22,9 +22,7 @@ public class SimpleCodeInsightTest extends LightCodeInsightFixtureTestCase {
} }
@Override @Override
protected String getTestDataPath() { protected String getTestDataPath() { return "testData"; }
return "code_samples/simple_language_plugin/testData";
}
public void testCompletion() { public void testCompletion() {
myFixture.configureByFiles("CompleteTestData.java", "DefaultTestData.simple"); myFixture.configureByFiles("CompleteTestData.java", "DefaultTestData.simple");
@ -41,15 +39,12 @@ public class SimpleCodeInsightTest extends LightCodeInsightFixtureTestCase {
public void testFormatter() { public void testFormatter() {
myFixture.configureByFiles("FormatterTestData.simple"); myFixture.configureByFiles("FormatterTestData.simple");
CodeStyleSettingsManager.getSettings(getProject()).SPACE_AROUND_ASSIGNMENT_OPERATORS = true; CodeStyle.getLanguageSettings(myFixture.getFile()).SPACE_AROUND_ASSIGNMENT_OPERATORS = true;
CodeStyleSettingsManager.getSettings(getProject()).KEEP_BLANK_LINES_IN_CODE = 2; CodeStyle.getLanguageSettings(myFixture.getFile()).KEEP_BLANK_LINES_IN_CODE = 2;
new WriteCommandAction.Simple(getProject()) { WriteCommandAction.writeCommandAction(getProject()).run(() -> {
@Override CodeStyleManager.getInstance(getProject()).reformatText(myFixture.getFile(),
protected void run() throws Throwable { ContainerUtil.newArrayList(myFixture.getFile().getTextRange()));
CodeStyleManager.getInstance(getProject()).reformatText(myFixture.getFile(), });
ContainerUtil.newArrayList(myFixture.getFile().getTextRange()));
}
}.execute();
myFixture.checkResultByFile("DefaultTestData.simple"); myFixture.checkResultByFile("DefaultTestData.simple");
} }

View File

@ -13,7 +13,7 @@ public class SimpleParsingTest extends ParsingTestCase {
@Override @Override
protected String getTestDataPath() { protected String getTestDataPath() {
return "code_samples/simple_language_plugin/testData"; return "testData";
} }
@Override @Override