-
Notifications
You must be signed in to change notification settings - Fork 308
/
CompilerSettings.scala
290 lines (247 loc) · 9.87 KB
/
CompilerSettings.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
/*
* Copyright 2005-2010 LAMP/EPFL
* @author Sean McDirmid
*/
// $Id$
package scala.tools.eclipse.properties
import org.eclipse.core.resources.{ IncrementalProjectBuilder, IProject }
import org.eclipse.core.runtime.preferences.IEclipsePreferences
import org.eclipse.jdt.core.IJavaProject
import org.eclipse.jface.preference.{ PreferencePage, IPersistentPreferenceStore, IPreferenceStore }
import org.eclipse.ui.{ IWorkbench, IWorkbenchPreferencePage }
import org.eclipse.ui.dialogs.PropertyPage
import org.eclipse.swt.SWT
import org.eclipse.swt.events.{ ModifyEvent, ModifyListener, SelectionAdapter, SelectionEvent, SelectionListener }
import org.eclipse.swt.layout.{ GridData, GridLayout, RowLayout }
import org.eclipse.swt.widgets.{ Button, Combo, Composite, Group, Label, Control, TabFolder, TabItem}
import scala.tools.nsc.Settings
import scala.tools.eclipse.{ ScalaPlugin, SettingConverterUtil }
import scala.tools.eclipse.util.IDESettings
trait ScalaPluginPreferencePage {
self: PreferencePage with EclipseSettings =>
val eclipseBoxes: List[EclipseSetting.EclipseBox]
def isChanged: Boolean = eclipseBoxes.exists(_.eSettings.exists(_.isChanged))
override def performDefaults = eclipseBoxes.foreach(_.eSettings.foreach(_.reset()))
def save(userBoxes: List[IDESettings.Box], store: IPreferenceStore): Unit = {
for (b <- userBoxes) {
for (setting <- b.userSettings) {
val name = SettingConverterUtil.convertNameToProperty(setting.name)
val isDefault = setting match {
case bs : Settings#BooleanSetting => bs.value == false
case is : Settings#IntSetting => is.value == is.default
case ss : Settings#StringSetting => ss.value == ss.default
case ms : Settings#MultiStringSetting => ms.value == Nil
case cs : Settings#ChoiceSetting => cs.value == cs.default
}
if (isDefault)
store.setToDefault(name)
else {
val value = setting match {
case ms : Settings#MultiStringSetting => ms.value.mkString(" ")
case setting => setting.value.toString
}
store.setValue(name, value)
}
}
}
store match {
case savable : IPersistentPreferenceStore => savable.save()
}
}
// There seems to be a bug in the compiler that appears in runtime (#2296)
// So updateApply is going to forward to real updateApplyButton
def updateApply: Unit
}
/**
* Provides a property page to allow Scala compiler settings to be changed.
*/
class CompilerSettings extends PropertyPage with IWorkbenchPreferencePage with EclipseSettings
with ScalaPluginPreferencePage {
//TODO - Use setValid to enable/disable apply button so we can only click the button when a property/preference
// has changed from the saved value
protected var isWorkbenchPage = false
override def init(workbench : IWorkbench) {
isWorkbenchPage = true
}
lazy val preferenceStore0 : IPreferenceStore = {
/** The project for which we are setting properties */
val project = getElement() match {
case project : IProject => Some(project)
case javaProject : IJavaProject => Some(javaProject.getProject())
case other => None // We're a Preference page!
}
if(project.isEmpty)
super.getPreferenceStore()
else
new PropertyStore(project.get, super.getPreferenceStore(), getPageId)
}
/** Returns the id of what preference page we use */
def getPageId = ScalaPlugin.plugin.pluginId
import EclipseSetting.toEclipseBox
/** The settings we can change */
lazy val userBoxes = IDESettings.shownSettings(new Settings) ++ IDESettings.buildManagerSettings
lazy val eclipseBoxes = userBoxes.map { s => toEclipseBox(s, preferenceStore0) }
/** Pulls the preference store associated with this plugin */
override def doGetPreferenceStore() : IPreferenceStore = {
ScalaPlugin.plugin.getPreferenceStore
}
var useProjectSettingsWidget : Option[UseProjectSettingsWidget] = None
def save(): Unit = {
if(useProjectSettingsWidget.isDefined) {
useProjectSettingsWidget.get.save
}
//This has to come later, as we need to make sure the useProjectSettingsWidget's values make it into
//the final save.
save(userBoxes, preferenceStore0)
//Don't let user click "apply" again until a change
updateApplyButton
}
def updateApply = updateApplyButton
/** Updates the apply button with the appropriate enablement. */
protected override def updateApplyButton() : Unit = {
if(getApplyButton != null) {
if(isValid) {
getApplyButton.setEnabled(isChanged)
} else {
getApplyButton.setEnabled(false)
}
}
}
// Eclipse PropertyPage API
def createContents(parent : Composite) : Control = {
val composite = {
if(isWorkbenchPage) {
//No Outer Composite
val tmp = new Composite(parent, SWT.NONE)
val layout = new GridLayout(1, false)
tmp.setLayout(layout)
val data = new GridData(GridData.FILL)
data.grabExcessHorizontalSpace = true
data.horizontalAlignment = GridData.FILL
tmp.setLayoutData(data)
tmp
} else {
//Create "Use Workspace Settings" button if on properties page...
val outer = new Composite(parent, SWT.NONE)
outer.setLayout(new GridLayout(1, false))
useProjectSettingsWidget = Some(new UseProjectSettingsWidget())
useProjectSettingsWidget.get.addTo(outer)
val tmp = new Group(outer, SWT.SHADOW_ETCHED_IN)
tmp.setText("Project Compiler Settings")
val layout = new GridLayout(1, false)
tmp.setLayout(layout)
val data = new GridData(GridData.FILL)
data.grabExcessHorizontalSpace = true
data.horizontalAlignment = GridData.FILL
tmp.setLayoutData(data)
tmp
}
}
val tabFolder = new TabFolder(composite, SWT.TOP)
eclipseBoxes.foreach(eBox => {
val group = new Group(tabFolder, SWT.SHADOW_ETCHED_IN)
group.setText(eBox.name)
val layout = new GridLayout(3, false)
group.setLayout(layout)
val data = new GridData(GridData.FILL)
data.grabExcessHorizontalSpace = true
data.horizontalAlignment = GridData.FILL
group.setLayoutData(data)
eBox.eSettings.foreach(_.addTo(group))
val tabItem = new TabItem(tabFolder, SWT.NONE)
tabItem.setText(eBox.name)
tabItem.setControl(group)
})
//Make sure we check enablement of compiler settings here...
useProjectSettingsWidget match {
case Some(widget) => widget.handleToggle
case None =>
}
tabFolder.pack()
composite
}
/** We override this so we can update the status of the apply button after all components have been added */
override def createControl(parent :Composite) : Unit = {
super.createControl(parent)
updateApplyButton
}
/** Check who needs to rebuild with new compiler flags */
private def buildIfNecessary() = {
getElement() match {
case project : IProject =>
//Make sure project is rebuilt
project.build(IncrementalProjectBuilder.CLEAN_BUILD, null)
case javaProject : IJavaProject =>
//Make sure project is rebuilt
javaProject.getProject().build(IncrementalProjectBuilder.CLEAN_BUILD, null)
case other =>
None // We're a Preference page!
//TODO - Figure out who needs to rebuild
}
}
// Eclipse PropertyPage API
override def performOk = try {
eclipseBoxes.foreach(_.eSettings.foreach(_.apply()))
save()
buildIfNecessary()
true
} catch {
case ex => ScalaPlugin.plugin.logError(ex); false
}
//Make sure apply button isn't available until it should be
override def isChanged : Boolean = {
useProjectSettingsWidget match {
case Some(widget) =>
if(widget.isChanged) {
return true
} else {
// Make sure we don't check the settings of the GUI if they're all disabled
// and the "use Project settings" is disabled
if(!widget.isUseEnabled)
return false
}
case None => //don't need to check
}
//check all our other settings
super.isChanged
}
/** This widget should only be used on property pages. */
class UseProjectSettingsWidget {
import SettingConverterUtil._
// TODO - Does this belong here? For now it's the only place we can really check...
if(!preferenceStore0.contains(USE_PROJECT_SETTINGS_PREFERENCE)) {
preferenceStore0.setDefault(USE_PROJECT_SETTINGS_PREFERENCE, false)
}
var control : Button = _
def layout = new GridData()
/** Pulls our current value from the preference store */
private def getValue = preferenceStore0.getBoolean(USE_PROJECT_SETTINGS_PREFERENCE)
/** Adds our widget to the Proeprty Page */
def addTo(page : Composite) = {
val container = new Composite(page, SWT.NONE)
container.setLayout(new GridLayout(2, false))
//Create Control
control = new Button(container, SWT.CHECK)
control.setSelection(getValue)
control.redraw
control.addSelectionListener(new SelectionListener() {
override def widgetDefaultSelected(e : SelectionEvent) {}
override def widgetSelected(e : SelectionEvent) { handleToggle }
})
val label = new Label(container, SWT.NONE)
label.setText("Use Project Settings")
}
/** Toggles the use of a property page */
def handleToggle = {
val selected = control.getSelection
eclipseBoxes.foreach(_.eSettings.foreach(_.setEnabled(selected)))
updateApplyButton
}
def isChanged = getValue != control.getSelection
def isUseEnabled = preferenceStore0.getBoolean(USE_PROJECT_SETTINGS_PREFERENCE)
/** Saves our value into the preference store*/
def save() {
preferenceStore0.setValue(USE_PROJECT_SETTINGS_PREFERENCE, control.getSelection)
}
}
}