Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add pub support #107

Merged
merged 19 commits into from Jul 31, 2019
Merged
Changes from 13 commits
Commits
File filter...
Filter file types
Jump to…
Jump to file or symbol
Failed to load files and symbols.

Always

Just for now

@@ -20,6 +20,11 @@
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ds.core.builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.PluginNature</nature>
@@ -25,5 +25,8 @@ Require-Bundle: org.eclipse.ui.genericeditor;bundle-version="1.0.0",
org.eclipse.tm4e.ui,
com.google.guava;bundle-version="21.0.0",
org.eclipse.lsp4j.jsonrpc
Import-Package: org.slf4j,
Import-Package: org.osgi.service.component.annotations;version="1.3.0",
org.slf4j,
org.slf4j.spi
Service-Component: OSGI-INF/org.eclipse.dartboard.ListenerService.xml
Bundle-ActivationPolicy: lazy
This conversation was marked as resolved by jonas-jonas

This comment has been minimized.

Copy link
@jonas-jonas

jonas-jonas Jul 22, 2019

Author Member

Is this correct?

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
This conversation was marked as resolved by jonas-jonas

This comment has been minimized.

Copy link
@jonas-jonas

jonas-jonas Jul 22, 2019

Author Member

This file should be committed right?

<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" activate="registerListeners" immediate="true" name="org.eclipse.dartboard.ListenerService">
<implementation class="org.eclipse.dartboard.ListenerService"/>
</scr:component>
@@ -6,6 +6,8 @@ Launch_NoProjectSelected_Body=Please select a project to launch
Launch_Project=Project:
Preference_SDKLocation=Dart SDK &Location:
Preference_SDKVersion=Dart SDK Version:
Preference_PubAutoSync_Label=Automatic &Pub dependency synchronization
Preference_PubOffline_Label=Use cached packages (--&offline flag)
Launch_SDKLocation_Message=The location the Dart SDK is installed to
Launch_MainClass=Main class:
Launch_MainClass_Message=Entry point to your Dart program
@@ -34,3 +36,11 @@ NewFile_Description=Create a new Dart file.
NewFile_Creating=Creating file {0}
NewFile_Container_Doesnot_Exist=Container {0} does not exist.
NewFile_OpeningFile=Opening file for editing...

PubSync_Job_Name=Resolving pub dependencies of {0}
PubSync_Task_ResolvingDependencies=Resolving dependencies...
PubSync_Task_PrecompilingExecutables=Precompiling executables...
PubSync_CouldNotDeterminePath=Could not determine path for project {0}. \n\
Maybe the project setup is defective?
PubSync_CouldNotStartProcess=Could not start pub process.
Error_CouldNotRefreshResource=Could not refresh resource {0}.
@@ -17,4 +17,5 @@ bin.includes = META-INF/,\
.,\
plugin.xml,\
assets/,\
OSGI-INF/,\
icons/
@@ -71,6 +71,34 @@
</visibleWhen>
</command>
</menuContribution>
<menuContribution
locationURI="popup:org.eclipse.ui.popup.any?after=additions">
<menu
id="org.eclipse.dartboard.pubmenuentry"
label="Pub">
<command
commandId="org.eclipse.dartboard.commands.pubget"
style="push">
</command>
<visibleWhen>
<with
variable="selection">
<count
value="1">
</count>
<iterate>
<adapt
type="org.eclipse.core.resources.IResource">
<test
forcePluginActivation="true"
property="org.eclipse.dartboard.isDartProject">
</test>
</adapt>
</iterate>
</with>
</visibleWhen>
</menu>
</menuContribution>
</extension>
<extension point="org.eclipse.debug.ui.launchShortcuts">
<shortcut class="org.eclipse.dartboard.launch.LaunchShortcut" id="org.eclipse.dartboard.run_as_shortcut" label="Run as Dart Program" icon="icons/dart.png" modes="run">
@@ -191,4 +219,27 @@
scopeName="source.dart">
</snippet>
</extension>
<extension
point="org.eclipse.ui.commands">
<command
description="Get the current package&apos;s dependencies."
id="org.eclipse.dartboard.commands.pubget"
name="Get dependencies">
</command>
</extension>
<extension
point="org.eclipse.ui.handlers">
<handler
class="org.eclipse.dartboard.pub.PubGetHandler"
commandId="org.eclipse.dartboard.commands.pubget">
</handler>
</extension>
<extension
point="org.eclipse.ui.commandImages">
<image
commandId="org.eclipse.dartboard.commands.pubget"
disabledIcon="platform:/plugin/org.eclipse.pde.ui/icons/dlcl16/refresh.png"
icon="platform:/plugin/org.eclipse.pde.ui/icons/elcl16/refresh.png">
</image>
</extension>
</plugin>
@@ -25,6 +25,16 @@ private Constants() {
*/
public static final String PREFERENCES_SDK_LOCATION = "sdk_location"; //$NON-NLS-1$

/**
* Preferences key for the option to automatically sync pub dependencies on pubspec.yaml file save.
*/
public static final String PREFERENCES_SYNC_PUB = "auto_pub_sync"; //$NON-NLS-1$

/**
* Preferences key for the --offline flag to pub get operations
*/
public static final String PREFERENCES_OFFLINE_PUB = "offline_pub"; //$NON-NLS-1$

/**
* Plugin ID of the plugin
*/
@@ -49,4 +59,15 @@ private Constants() {
* The ID of the Dart launch group
*/
public static final String LAUNCH_GROUP = "org.eclipse.dartboard.launchGroup"; //$NON-NLS-1$

/**
* Name of the pubspec file
*/
public static final String PUBSPEC = "pubspec.yaml"; //$NON-NLS-1$

/**
* Name of the PUB_ENVIRONMENT variable used by pub
*/
public static final String PUB_ENVIRONMENT_VARIABLE = "PUB_ENVIRONMENT"; //$NON-NLS-1$

}
@@ -0,0 +1,31 @@
/*******************************************************************************
* Copyright (c) 2019 vogella GmbH and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Jonas Hungershausen - initial API and implementation
*******************************************************************************/
package org.eclipse.dartboard;

import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.dartboard.pub.PubspecChangeListener;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;

@Component(immediate = true)
public class ListenerService {

@Activate
public void registerListeners() {
IWorkspace workspace = ResourcesPlugin.getWorkspace();
workspace.addResourceChangeListener(new PubspecChangeListener());
This conversation was marked as resolved by jonas-jonas

This comment has been minimized.

Copy link
@lak-proddev

lak-proddev Jul 30, 2019

Contributor

Don't need to create an object for IWorkspace. We can call directly ResourcesPlugin.getWorkspace().addResourceChangeListener(new PubspecChangeListener());

This comment has been minimized.

Copy link
@jonas-jonas

jonas-jonas Jul 30, 2019

Author Member

Not now, but maybe later. There is no harm in having it this way.

This comment has been minimized.

Copy link
@lak-proddev

lak-proddev Jul 30, 2019

Contributor

There is no harm. except creating an unnecessary object reference :)

This comment has been minimized.

Copy link
@lak-proddev

lak-proddev Jul 30, 2019

Contributor

Don't we need to remove the listener?. I am not sure.

This comment has been minimized.

Copy link
@jonas-jonas

jonas-jonas Jul 30, 2019

Author Member

Yes, ideally we would remove the listener when the user unchecks the checkbox on the preference page. But as the ListenerService is not available in the class in the current design, the listener stays registered as is and the necessary checks are done whenever it fires.

And it should stay registered until the workspace is closed.

}

}
@@ -26,6 +26,8 @@
public static String Launch_Project;
public static String Preference_SDKLocation;
public static String Preference_SDKVersion;
public static String Preference_PubAutoSync_Label;
public static String Preference_PubOffline_Label;
public static String Launch_SDKLocation_Message;
public static String Launch_MainClass;
public static String Launch_MainClass_Message;
@@ -54,6 +56,12 @@
public static String NewFile_Creating;
public static String NewFile_Container_Doesnot_Exist;
public static String NewFile_OpeningFile;
public static String PubSync_Job_Name;
public static String PubSync_Task_ResolvingDependencies;
public static String PubSync_Task_PrecompilingExecutables;
public static String PubSync_CouldNotDeterminePath;
public static String PubSync_CouldNotStartProcess;
public static String Error_CouldNotRefreshResource;

static {
NLS.initializeMessages("assets.messages", Messages.class);
@@ -20,11 +20,11 @@
import java.nio.file.Paths;
import java.util.Optional;

import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.dartboard.Constants;
import org.eclipse.dartboard.Messages;
import org.eclipse.dartboard.util.DartUtil;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.ui.preferences.ScopedPreferenceStore;
import org.slf4j.Logger;
@@ -58,6 +58,8 @@ public void initializeDefaultPreferences() {
Messages.Preference_SDKNotFound_Body);
}
}
scopedPreferenceStore.setDefault(Constants.PREFERENCES_SYNC_PUB, true);
scopedPreferenceStore.setDefault(Constants.PREFERENCES_OFFLINE_PUB, false);
}

/**
@@ -79,7 +81,7 @@ public void initializeDefaultPreferences() {
public Optional<Path> getDartLocation() {
Path path = null; // $NON-NLS-1$
String[] command;
if (Platform.OS_WIN32.equals(Platform.getOS())) {
if (DartUtil.IS_WINDOWS) {
command = new String[] { "cmd", "/c", "where dart" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
} else {
command = new String[] { "/bin/bash", "-c", "which dart" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
@@ -23,6 +23,7 @@
import org.eclipse.dartboard.Constants;
import org.eclipse.dartboard.Messages;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.preference.BooleanFieldEditor;
import org.eclipse.jface.preference.DirectoryFieldEditor;
import org.eclipse.jface.preference.FieldEditor;
import org.eclipse.jface.preference.FieldEditorPreferencePage;
@@ -54,6 +55,13 @@
*/
private DartSDKLocationFieldEditor dartSDKLocationEditor;

private BooleanFieldEditor autoPubSyncEditor;
private BooleanFieldEditor useOfflinePub;

public DartPreferencePage() {
super(GRID);
}

/**
* Initializes the {@link DartPreferencePage#getPreferenceStore()} to the
* default preference store of the plugin
@@ -67,6 +75,8 @@ public void init(IWorkbench workbench) {
public boolean performOk() {
String sdkLocation = dartSDKLocationEditor.getStringValue();
String oldValue = getPreferenceStore().getString(Constants.PREFERENCES_SDK_LOCATION);

boolean ok = super.performOk();
// Don't update the preference store if the oldValue matches the new value
if (sdkLocation.equals(oldValue)) {
return true;
@@ -81,7 +91,6 @@ public boolean performOk() {

dartSDKLocationEditor.setStringValue(path.toAbsolutePath().toString());

boolean ok = super.performOk();
boolean result = MessageDialog.openQuestion(null, Messages.Preference_RestartRequired_Title,
Messages.Preference_RestartRequired_Message);

@@ -93,7 +102,7 @@ public boolean performOk() {
} catch (IOException e) {
e.printStackTrace();
}

Display.getDefault().asyncExec(() -> {
PlatformUI.getWorkbench().restart(true);
});
@@ -137,6 +146,12 @@ protected void createFieldEditors() {
dartSDKLocationEditor.addModifyListener(event -> {
setValid(dartSDKLocationEditor.doCheckState());
});
autoPubSyncEditor = new BooleanFieldEditor(Constants.PREFERENCES_SYNC_PUB,
Messages.Preference_PubAutoSync_Label, parent);
addField(autoPubSyncEditor);
useOfflinePub = new BooleanFieldEditor(Constants.PREFERENCES_OFFLINE_PUB, Messages.Preference_PubOffline_Label,
parent);
addField(useOfflinePub);
}

/**
@@ -88,7 +88,7 @@ private IProject createNewProject() {
Messages.NewProject_WindowTitle);
try {
projectOperation.execute(monitor, WorkspaceUndoUtil.getUIInfoAdapter(getShell()));
IFile pubspecFile = newProjectHandle.getFile("pubspec.yaml"); //$NON-NLS-1$
IFile pubspecFile = newProjectHandle.getFile(Constants.PUBSPEC); // $NON-NLS-1$
if (!pubspecFile.exists()) {
pubspecFile.create(new NullInputStream(0), true, null);
}
@@ -18,6 +18,7 @@
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.Adapters;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.dartboard.Constants;

public class IsDartProjectPropertyTester extends PropertyTester {

@@ -38,7 +39,7 @@ public boolean test(Object receiver, String property, Object[] args, Object expe

try {
for (IResource res : project.members()) {
if ("pubspec.yaml".equals(res.getName()) || "dart".equals(res.getFileExtension())) { //$NON-NLS-1$ //$NON-NLS-2$
if (Constants.PUBSPEC.equals(res.getName()) || "dart".equals(res.getFileExtension())) { //$NON-NLS-1$
This conversation was marked as resolved by jonas-jonas

This comment has been minimized.

Copy link
@lak-proddev

lak-proddev Jul 30, 2019

Contributor

Since we know the default path. We can check in the default path using #findMember(String)
If not found, we need to iterate all the members.

This comment has been minimized.

Copy link
@jonas-jonas

jonas-jonas Jul 30, 2019

Author Member

Done

return true;
}
}
@@ -0,0 +1,36 @@
package org.eclipse.dartboard.pub;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.Adapters;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.dartboard.Constants;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.ui.handlers.HandlerUtil;
import org.eclipse.ui.preferences.ScopedPreferenceStore;

public class PubGetHandler extends AbstractHandler {

private PubService pub;

private ScopedPreferenceStore preferences;

public PubGetHandler() {
pub = PubService.getInstance();
This conversation was marked as resolved by jonas-jonas

This comment has been minimized.

Copy link
@lak-proddev

lak-proddev Jul 30, 2019

Contributor

Same here also. You can directly call the static method instead of creating an object.

This comment has been minimized.

Copy link
@jonas-jonas

jonas-jonas Jul 30, 2019

Author Member

PubService is supposed to be a Singleton. And since it has some Data stored, it would not be ideal to make it all static.

Ideally I would like to provide it as an OSGi service and have it injected into the classes I need it. This however is not possible for pages (see DartPreferencePage) that are defined via extension points. At least I could not figure out how to do so.

Once we have a working OSGi service structure for this, the refactoring would be minimal, as we can just add a @Inject to the field instead of changing all method calls to be non-static. That's why I used the Singlet pattern for now.

preferences = new ScopedPreferenceStore(InstanceScope.INSTANCE, Constants.PLUGIN_ID);
This conversation was marked as resolved by jonas-jonas

This comment has been minimized.

Copy link
@lak-proddev

lak-proddev Jul 30, 2019

Contributor

I think it's not the right place to create the object. Is the preference store object is not available at this point? If not, we need to create in startup class and need to access like activator

  public IPreferenceStore getPreferenceStore() {
  	if (preferenceStore == null) {
  		preferenceStore = new ScopedPreferenceStore(InstanceScope.INSTANCE, Constants.PLUGIN_ID);

  	}
  	return preferenceStore;
  }

This comment has been minimized.

Copy link
@jonas-jonas

jonas-jonas Jul 30, 2019

Author Member

I'm not sure what the benefit of a globally accessible constant/variable would be. Again, it would be nice to have it as an @Inject'able service, but I have not figured out how to do this. I will have to wait for @vogella for advice on this.

Also it is done this way all over the codebase right now and would require a major refactor that is IMO out of scope of this PR.

}

@Override
public Object execute(ExecutionEvent event) throws ExecutionException {
ISelection sel = HandlerUtil.getCurrentSelection(event);
This conversation was marked as resolved by jonas-jonas

This comment has been minimized.

Copy link
@lak-proddev

lak-proddev Jul 30, 2019

Contributor

We can use directly org.eclipse.ui.handlers.HandlerUtil.getCurrentStructuredSelection(ExecutionEvent). Instead of typecasting.

if (sel instanceof IStructuredSelection) {
IResource res = Adapters.adapt(((IStructuredSelection) sel).getFirstElement(), IResource.class);
This conversation was marked as resolved by jonas-jonas

This comment has been minimized.

Copy link
@lak-proddev

lak-proddev Jul 30, 2019

Contributor

Do we really need to call the adapt method? I think we can write like this

		IStructuredSelection structuredSelection = HandlerUtil.getCurrentStructuredSelection(event);
		if (structuredSelection.getFirstElement() instanceof IResource) {
                         // Do it
		}

pub.get(res.getProject(), preferences.getBoolean(Constants.PREFERENCES_OFFLINE_PUB));
}
return null;
}

}
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.