Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

We’re showing branches in this repository, but you can also compare across forks.

...
  • 10 commits
  • 24 files changed
  • 0 commit comments
  • 3 contributors
Commits on Mar 27, 2013
Iulian Dragos dragos Avoid calling Option.get f47a629
Iulian Dragos dragos Don't connect and disconnect a model to the document.
This is entirely unnecessary, an annotation model is connected for the lifetime
of an editor. This gives rise to a race condition in `Save`.

Fixed #24.
b5fe928
Iulian Dragos dragos Cleanup in error annotations.
Don't accumulate annotations in "previousAnnotations" and don't create error
markers during reconciliation.

Fixed #47.
fdaded1
Mirco Dotta dotta Merge pull request #52 from dragos/issue/fix-save-failed-24
Save Failed assertion failed and small cleanups in error annotations.
8f1e3f7
Mirco Dotta dotta Use Tycho 0.16 and updated scala versions in POM
* Updated the README build example to use the ``scala-ide-stable``
  profile. Why? Because this is going to make it easier for people to
  start hacking as it is the stable update-site. As a consequence,
  ``eclipse-indigo`` is now used (that the Eclipse version that is
  currently  supported by the 3.0.0 IDE release).

* Removed scala-2.9.x profile because Play 2.1 only supports Scala 2.10
87f4784
Mirco Dotta dotta Created a TestSuite class for running all tests in the regression suite
* Updated the POM to run the new ``TestSuite`` class.
b3b3270
Commits on Mar 28, 2013
Mirco Dotta dotta Graceful handling of parsing errors from template compiler
* Because the Play template compiler throws an exception as soon as a parsing error is
encountered, calls to the Play template compiler are now wrapped in a ``Try``.
It's the responsability of the calling code to handle the failure case as it
makes sense.

* Use ``Annotation`` for reporting both parsing and compilation errors from
template files. The implication of this is that compilation  errors are no longer
displayed in the Problem View or the Package Explorer.

* Because we now solely use Annotation, we no longer need to use the Eclipse
extension point for defining new markers (look at the deleted lines in
plugin.xml).

* Finally, I'm aware that the code could use some more clean-up, but my intention
was to minimize changes as we plan to release 0.1 possibly next week already.

Fixes #29
be83b7f
Mirco Dotta dotta Merge pull request #54 from dotta/issue/catch-errors-from-template-co…
…mpiler-29

Issue/catch errors from template compiler 29
45005d9
Iulian Dragos dragos Don't restrict where templates can be located..
.. but log a warning in the Log (in case this proves a bad idea).

Fixed #45.
5c7dd65
Commits on Apr 03, 2013
Luc Bourlier Adds a preference and an project preference page
The preference is initialized with framework defaults (play.api.templates._, play.api.templates.PlayMagic._).
It can be overriden at the project level, in the project properties.
Changes are not applied directly, as we are currently lacking a real builder.

Fix #35.
ccc7675
Showing with 540 additions and 368 deletions.
  1. +7 −9 README.md
  2. +1 −2  org.scala-ide.play2.tests/pom.xml
  3. +11 −0 org.scala-ide.play2.tests/src/org/scalaide/play2/TestSuite.scala
  4. +21 −8 org.scala-ide.play2.tests/src/org/scalaide/play2/templateeditor/lexical/TemplateCompilationUnitTest.scala
  5. +5 −0 org.scala-ide.play2.tests/test-workspace/aProject/app/views/scala_compiler_error.scala.html
  6. +5 −0 org.scala-ide.play2.tests/test-workspace/aProject/app/views/template_parse_error.scala.html
  7. +43 −35 org.scala-ide.play2/plugin.xml
  8. +11 −8 org.scala-ide.play2/src/org/scalaide/play2/PlayPlugin.scala
  9. +9 −1 org.scala-ide.play2/src/org/scalaide/play2/PlayProject.scala
  10. +35 −0 org.scala-ide.play2/src/org/scalaide/play2/properties/PlayPreferences.scala
  11. +12 −0 org.scala-ide.play2/src/org/scalaide/play2/properties/PreferenceInitializer.scala
  12. +83 −0 org.scala-ide.play2/src/org/scalaide/play2/properties/ProjectPropertyPage.scala
  13. +31 −50 org.scala-ide.play2/src/org/scalaide/play2/templateeditor/TemplateCompilationUnit.scala
  14. +33 −22 org.scala-ide.play2/src/org/scalaide/play2/templateeditor/TemplateEditor.scala
  15. +38 −19 org.scala-ide.play2/src/org/scalaide/play2/templateeditor/compiler/CompilerUsing.scala
  16. +54 −64 org.scala-ide.play2/src/org/scalaide/play2/templateeditor/compiler/TemplatePresentationCompiler.scala
  17. +15 −11 org.scala-ide.play2/src/org/scalaide/play2/templateeditor/completion/CompletionProposalComputer.scala
  18. +4 −2 org.scala-ide.play2/src/org/scalaide/play2/templateeditor/hover/TemplateHover.scala
  19. +29 −20 org.scala-ide.play2/src/org/scalaide/play2/templateeditor/hyperlink/LocalTemplateHyperlinkComputer.scala
  20. +9 −3 org.scala-ide.play2/src/org/scalaide/play2/templateeditor/hyperlink/TemplateDeclarationHyperlinkDetector.scala
  21. +8 −47 org.scala-ide.play2/src/org/scalaide/play2/templateeditor/reconciler/TemplateReconcilingStrategy.scala
  22. +36 −0 org.scala-ide.play2/src/org/scalaide/play2/util/Play2PropertyTester.scala
  23. +16 −0 org.scala-ide.play2/src/org/scalaide/play2/util/SyncedScopedPreferenceStore.scala
  24. +24 −67 pom.xml
16 README.md
View
@@ -1,6 +1,6 @@
-# Scala IDE plugin for Play 2.x
+# Scala IDE plugin for Play 2.1
-This is an extension to Scala IDE to support Play 2.x routes and template files.
+This is an extension to Scala IDE to support Play 2.1 routes and template files.
For user documentation, check the [wiki](https://github.com/scala-ide/scala-ide-play2/wiki).
@@ -18,19 +18,17 @@ The projects can be imported inside Scala IDE. And they are fully configured to
## Building
-The maven build is configured using a combination of 3 profiles:
+The maven build is configured using a combination of 2 profiles:
* An Eclipse platform profile:
* `eclipse-indigo`
* `eclipse-juno`
-* A Scala version profile:
- * `scala-2.9.x`
- * `scala-2.10.x`
+
* A Scala IDE version profile:
- * `scala-ide-nightly`
+ * `scala-ide-stable`
* `scala-ide-dev`
- * `scala-ide-stable` (not available yet)
+ * `scala-ide-nightly`
After choosing the flavor you wish to build, maven is run using:
- mvn -Peclipse-juno -Pscala-2.10.x -Pscala-ide-dev clean package
+ mvn -Peclipse-indigo -Pscala-ide-stable clean package
3  org.scala-ide.play2.tests/pom.xml
View
@@ -16,8 +16,7 @@
<artifactId>tycho-surefire-plugin</artifactId>
<configuration>
<testSuite>${project.artifactId}</testSuite>
- <testClass>org.scalaide.play2.RouteTestSuite</testClass>
- <testClass>org.scalaide.play2.TemplateTestSuite</testClass>
+ <testClass>org.scalaide.play2.TestSuite</testClass>
</configuration>
</plugin>
</plugins>
11 org.scala-ide.play2.tests/src/org/scalaide/play2/TestSuite.scala
View
@@ -0,0 +1,11 @@
+package org.scalaide.play2
+
+import org.junit.runner.RunWith
+import org.junit.runners.Suite.SuiteClasses
+
+@RunWith(value=classOf[org.junit.runners.Suite])
+@SuiteClasses(value=Array(
+ classOf[RouteTestSuite],
+ classOf[TemplateTestSuite]
+))
+class TestSuite
29 org.scala-ide.play2.tests/src/org/scalaide/play2/templateeditor/lexical/TemplateCompilationUnitTest.scala
View
@@ -1,13 +1,13 @@
package org.scalaide.play2.templateeditor.lexical
+import scala.tools.eclipse.testsetup.SDTTestUtils
import scala.tools.eclipse.testsetup.TestProjectSetup
-import org.junit.Test
-import org.junit.Assert._
-import org.scalaide.play2.templateeditor.TemplateCompilationUnit
+
import org.eclipse.jdt.internal.core.util.SimpleDocument
-import scala.tools.eclipse.testsetup.FileUtils
import org.junit.AfterClass
-import scala.tools.eclipse.testsetup.SDTTestUtils
+import org.junit.Assert._
+import org.junit.Test
+import org.scalaide.play2.templateeditor.TemplateCompilationUnit
object TemplateCompilationUnitTest extends TestProjectSetup("aProject", bundleName = "org.scala-ide.play2.tests") {
@AfterClass
@@ -35,23 +35,36 @@ class TemplateCompilationUnitTest {
val document = new TestDocument(content1)
templateCU.connect(document)
- val generated1 = templateCU.generatedSource.content
+ val generated1 = templateCU.generatedSource.get.content
val content2 = "@(messages: String)\n<html><body>@messages</body></html>\n"
document.set(content2)
- val generated2 = templateCU.generatedSource.content
+ val generated2 = templateCU.generatedSource.get.content
assertFalse("generated1 and generated2 should be different", generated1 == generated2)
document.set(content1)
- val generated1_2 = templateCU.generatedSource.content
+ val generated1_2 = templateCU.generatedSource.get.content
assertEquals("Same content should return the same generated code", generated1, generated1_2)
}
+ @Test
+ def no_scala_source_is_generated_when_there_are_template_parse_errors() {
+ val tFile = file("app/views/template_parse_error.scala.html")
+ val tu = TemplateCompilationUnit(tFile)
+ assertTrue(tu.generatedSource.isFailure)
+ }
+
+ @Test
+ def scala_source_is_generated_when_there_are_scala_compiler__errors() {
+ val tFile = file("app/views/scala_compiler_error.scala.html")
+ val tu = TemplateCompilationUnit(tFile)
+ assertTrue(tu.generatedSource.isSuccess)
+ }
}
/**
5 org.scala-ide.play2.tests/test-workspace/aProject/app/views/scala_compiler_error.scala.html
View
@@ -0,0 +1,5 @@
+@(message: String)
+
+@main("Welcome") {
+ <p>@foo</p>
+}
5 org.scala-ide.play2.tests/test-workspace/aProject/app/views/template_parse_error.scala.html
View
@@ -0,0 +1,5 @@
+@(message: String)
+
+@main("Welcome") {
+ <p>@</p>
+}
78 org.scala-ide.play2/plugin.xml
View
@@ -71,41 +71,9 @@
<initializer
class="org.scalaide.play2.templateeditor.properties.TemplateColourPreferenceInitializer">
</initializer>
- </extension>
- <extension
- point="org.eclipse.ui.editors.annotationTypes">
- <type
- markerSeverity="2"
- markerType="org.scala-ide.play2.templateProblem"
- name="org.scala-ide.play2.error"
- super="org.eclipse.ui.workbench.texteditor.error">
- </type>
- <type
- markerSeverity="1"
- markerType="org.scala-ide.play2.templateProblem"
- name="org.scala-ide.play2.warning"
- super="org.eclipse.ui.workbench.texteditor.warning">
- </type>
- <type
- markerSeverity="0"
- markerType="org.scala-ide.play2.templateProblem"
- name="org.scala-ide.play2.info"
- super="org.eclipse.ui.workbench.texteditor.info">
- </type>
- </extension>
- <extension
- id="templateProblem"
- name="Template Problem"
- point="org.eclipse.core.resources.markers">
- <super
- type="org.eclipse.core.resources.problemmarker">
- </super>
- <super
- type="org.eclipse.core.resources.textmarker">
- </super>
- <persistent
- value="false">
- </persistent>
+ <initializer
+ class="org.scalaide.play2.properties.PreferenceInitializer">
+ </initializer>
</extension>
<extension
point="org.eclipse.core.contenttype.contentTypes">
@@ -173,6 +141,46 @@
name="Format">
</command>
</extension>
+ <extension
+ point="org.eclipse.core.expressions.propertyTesters">
+ <propertyTester
+ class="org.scalaide.play2.util.Play2PropertyTester"
+ id="org.scala-ide.play2.isJavaPlayProject"
+ namespace="org.scala-ide.play2.properties"
+ properties="isPlay2Project"
+ type="org.eclipse.jdt.core.IJavaProject">
+ </propertyTester>
+ <propertyTester
+ class="org.scalaide.play2.util.Play2PropertyTester"
+ id="org.scala-ide.play2.isPlayProject"
+ namespace="org.scala-ide.play2.properties"
+ properties="isPlay2Project"
+ type="org.eclipse.core.resources.IProject">
+ </propertyTester>
+ </extension>
+ <extension
+ point="org.eclipse.ui.propertyPages">
+ <page
+ class="org.scalaide.play2.properties.ProjectPropertyPage"
+ id="org.scala-ide.play2.projectPropertyPage"
+ name="Play2">
+ <enabledWhen>
+ <and>
+ <or>
+ <instanceof
+ value="org.eclipse.jdt.core.IJavaProject">
+ </instanceof>
+ <instanceof
+ value="org.eclipse.core.resources.IProject">
+ </instanceof>
+ </or>
+ <test
+ property="org.scala-ide.play2.properties.isPlay2Project">
+ </test>
+ </and>
+ </enabledWhen>
+ </page>
+ </extension>
<!--
<extension
point="org.eclipse.ui.editors.markerAnnotationSpecification">
19 org.scala-ide.play2/src/org/scalaide/play2/PlayPlugin.scala
View
@@ -5,12 +5,12 @@ import org.eclipse.core.resources.IProject
import org.eclipse.ui.plugin.AbstractUIPlugin
import org.osgi.framework.BundleContext
import org.eclipse.core.resources.ResourcesPlugin
+import org.eclipse.core.runtime.Status
object PlayPlugin {
@volatile var plugin: PlayPlugin = _
- private final val PluginId = "org.scala-ide.play2"
- final val ProblemMarkerId = PluginId + ".templateProblem"
+ final val PluginId = "org.scala-ide.play2"
final val RouteFormatterMarginId = PluginId + ".routeeditor.margin"
final val TemplateExtension = "scala.html"
@@ -19,19 +19,23 @@ object PlayPlugin {
def getImageDescriptor(path: String) = {
AbstractUIPlugin.imageDescriptorFromPlugin(PluginId, path);
}
+
+ def log(status: Int, msg: String, ex: Throwable = null) {
+ plugin.getLog.log(new Status(status, plugin.getBundle().getSymbolicName(), msg, ex))
+ }
}
class PlayPlugin extends AbstractUIPlugin {
import PlayPlugin._
override def start(context: BundleContext) = {
- super.start(context);
- PlayPlugin.plugin = this;
+ super.start(context)
+ PlayPlugin.plugin = this
initializeProjects()
}
override def stop(context: BundleContext) = {
- PlayPlugin.plugin = null;
- super.stop(context);
+ PlayPlugin.plugin = null
+ super.stop(context)
}
def asPlayProject(project: IProject): Option[PlayProject] = {
@@ -46,5 +50,4 @@ class PlayPlugin extends AbstractUIPlugin {
playProject <- asPlayProject(iProject)
} playProject.initialize()
}
-
-}
+}
10 org.scala-ide.play2/src/org/scalaide/play2/PlayProject.scala
View
@@ -8,15 +8,23 @@ import org.eclipse.core.resources.IFile
import org.scalaide.play2.templateeditor.TemplateCompilationUnit
import org.scalaide.play2.templateeditor.compiler.TemplatePresentationCompiler
import org.scalaide.play2.util.AutoHashMap
+import org.eclipse.ui.preferences.ScopedPreferenceStore
+import org.eclipse.core.resources.ProjectScope
+import org.scalaide.play2.util.SyncedScopedPreferenceStore
+import org.eclipse.jface.preference.IPreferenceStore
class PlayProject private (val scalaProject: ScalaProject) {
private val presentationCompiler = new TemplatePresentationCompiler(this)
+ val cachedPreferenceStore = new SyncedScopedPreferenceStore(scalaProject.underlying, PlayPlugin.PluginId)
+
+ def generateScopedPreferenceStore: IPreferenceStore = new ScopedPreferenceStore(new ProjectScope(scalaProject.underlying), PlayPlugin.PluginId)
+
def withPresentationCompiler[T](op: TemplatePresentationCompiler => T): T = {
op(presentationCompiler)
}
- def withSourceFile[T](tcu: TemplateCompilationUnit)(op: (SourceFile, ScalaPresentationCompiler) => T): T = {
+ def withSourceFile[T](tcu: TemplateCompilationUnit)(op: (SourceFile, ScalaPresentationCompiler) => T): Option[T] = {
withPresentationCompiler { compiler =>
compiler.withSourceFile(tcu)(op)
}
35 org.scala-ide.play2/src/org/scalaide/play2/properties/PlayPreferences.scala
View
@@ -16,6 +16,41 @@ import org.eclipse.ui.IWorkbenchPreferencePage
import org.eclipse.ui.dialogs.PropertyPage
import org.scalaide.play2.PlayPlugin
+object PlayPreferences {
+
+ /** Preference containing the list of import to automatically add to the generate template code.
+ * The data is stored as the string which will be added to the generated source (to not recreate
+ * it everytime). The empty String represent an empty import list.
+ * [[org.scalaide.play2.properties.PlayPreferences.serializeImports]] and [[org.scalaide.play2.properties.PlayPreferences.deserializeImports]]
+ * need to be used when converting the preference value to/from Array[String].
+ */
+ final val TemplateImports = "templateImports"
+
+ // Regex used for the operations on the templateImports preference.
+ private val importsRegex = "import ([^\n]+)\n".r
+
+ /** @see [[org.scalaide.play2.properties.PlayPreferences.TemplateImports]]
+ */
+ def serializeImports(entries: Array[String]): String = {
+ if (entries.length == 0) {
+ ""
+ } else {
+ entries.mkString("import ", "\nimport ", "\n")
+ }
+ }
+
+ /** @see [[org.scalaide.play2.properties.PlayPreferences.TemplateImports]]
+ */
+ def deserializeImports(s: String): Array[String] = {
+ if (s.length == 0) {
+ new Array(0)
+ } else {
+ importsRegex.findAllIn(s).matchData.map(m => m.group(1)).toArray
+ }
+ }
+
+}
+
class PlayPreferences extends PropertyPage with IWorkbenchPreferencePage with EclipseSettings
with ScalaPluginPreferencePage with HasLogger {
12 org.scala-ide.play2/src/org/scalaide/play2/properties/PreferenceInitializer.scala
View
@@ -0,0 +1,12 @@
+package org.scalaide.play2.properties
+
+import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer
+import org.scalaide.play2.PlayPlugin
+
+class PreferenceInitializer extends AbstractPreferenceInitializer {
+
+ override def initializeDefaultPreferences() {
+ PlayPlugin.prefStore.setDefault(PlayPreferences.TemplateImports, "import play.api.templates._\nimport play.api.templates.PlayMagic._\n")
+ }
+
+}
83 org.scala-ide.play2/src/org/scalaide/play2/properties/ProjectPropertyPage.scala
View
@@ -0,0 +1,83 @@
+package org.scalaide.play2.properties
+
+import org.eclipse.core.resources.IProject
+import org.eclipse.core.runtime.IAdaptable
+import org.eclipse.jdt.core.IJavaProject
+import org.eclipse.jface.dialogs.IInputValidator
+import org.eclipse.jface.dialogs.InputDialog
+import org.eclipse.jface.preference.FieldEditorPreferencePage
+import org.eclipse.jface.preference.IPreferenceStore
+import org.eclipse.jface.preference.ListEditor
+import org.eclipse.jface.window.Window
+import org.eclipse.swt.widgets.Composite
+import org.eclipse.swt.widgets.Display
+import org.eclipse.ui.IWorkbenchPropertyPage
+import org.scalaide.play2.PlayPlugin
+
+/** Preference page displayed in the property dialog of (play) projects.
+ * Used from the UI thread.
+ */
+class ProjectPropertyPage extends FieldEditorPreferencePage(FieldEditorPreferencePage.GRID) with IWorkbenchPropertyPage {
+
+ /** Preference field to display the list of extra imports.
+ */
+ private class ImportsFieldEditor(name: String, labelText: String, parent: Composite) extends ListEditor(name, labelText, parent) {
+
+ override protected def createList(entries: Array[String]): String =
+ PlayPreferences.serializeImports(entries)
+
+ override protected def parseString(s: String): Array[String] =
+ PlayPreferences.deserializeImports(s)
+
+ override protected def getNewInputObject(): String = {
+
+ val dlg = new InputDialog(
+ Display.getCurrent().getActiveShell(),
+ "Play template import",
+ "Enter an import value:",
+ "com.example._",
+ new IInputValidator {
+ def isValid(text: String) = null
+ });
+
+ if (dlg.open() == Window.OK) {
+ dlg.getValue()
+ } else {
+ null
+ }
+ }
+
+ }
+
+ // The preference store being edited.
+ // The data require to get the store is provided by the workbench during the page lifecycle.
+ var prefStore: IPreferenceStore = _
+
+ // Members declared in org.eclipse.jface.preference.FieldEditorPreferencePage
+
+ override def createFieldEditors() {
+ addField(new ImportsFieldEditor(PlayPreferences.TemplateImports, "Template default imports", getFieldEditorParent()))
+ }
+
+ // Members declared in org.eclipse.ui.IWorkbenchPropertyPage
+
+ // doesn't seem to be a real function for this method.
+ // It looks like it leaked from the implementation of PropertyPage.
+ override def getElement(): IAdaptable = null
+
+ override def setElement(element: IAdaptable) {
+ prefStore = element match {
+ case project: IProject =>
+ PlayPlugin.plugin.asPlayProject(project).get.generateScopedPreferenceStore
+ case project: IJavaProject =>
+ PlayPlugin.plugin.asPlayProject(project.getProject()).get.generateScopedPreferenceStore
+ }
+ }
+
+ // ----
+
+ override def doGetPreferenceStore(): IPreferenceStore = {
+ prefStore
+ }
+
+}
81 org.scala-ide.play2/src/org/scalaide/play2/templateeditor/TemplateCompilationUnit.scala
View
@@ -1,40 +1,38 @@
package org.scalaide.play2.templateeditor
-import java.io.File
+import java.io.PrintStream
+
import scala.tools.eclipse.InteractiveCompilationUnit
import scala.tools.eclipse.ScalaPlugin
import scala.tools.eclipse.ScalaPresentationCompiler
-import scala.tools.eclipse.resources.MarkerFactory
-import scala.tools.eclipse.util.EclipseFile
+import scala.tools.eclipse.logging.HasLogger
import scala.tools.eclipse.util.EclipseResource
import scala.tools.nsc.interactive.Response
import scala.tools.nsc.io.AbstractFile
+import scala.tools.nsc.io.VirtualFile
import scala.tools.nsc.util.BatchSourceFile
import scala.tools.nsc.util.SourceFile
+import scala.util.Try
+
import org.eclipse.core.resources.IFile
-import org.eclipse.core.resources.IMarker
-import org.eclipse.core.resources.IResource
import org.eclipse.jdt.core.compiler.IProblem
import org.eclipse.jface.text.IDocument
-import org.eclipse.jface.text.Position
+import org.eclipse.jface.text.IRegion
import org.eclipse.jface.text.Region
import org.eclipse.ui.IEditorInput
import org.eclipse.ui.part.FileEditorInput
-import org.eclipse.ui.texteditor.ITextEditor
import org.scalaide.play2.PlayPlugin
import org.scalaide.play2.PlayProject
-import org.scalaide.play2.templateeditor.compiler.PositionHelper
-import scala.tools.nsc.io.VirtualFile
-import java.io.PrintStream
-import org.eclipse.jface.text.IRegion
import org.scalaide.play2.templateeditor.compiler.CompilerUsing
+import org.scalaide.play2.templateeditor.compiler.PositionHelper
+
import play.templates.GeneratedSourceVirtual
/** A Template compilation unit connects the presentation compiler
* view of a tmeplate with the Eclipse IDE view of the underlying
* resource.
*/
-case class TemplateCompilationUnit(val workspaceFile: IFile) extends InteractiveCompilationUnit {
+case class TemplateCompilationUnit(val workspaceFile: IFile) extends InteractiveCompilationUnit with HasLogger {
private var document: Option[IDocument] = None
@@ -71,7 +69,7 @@ case class TemplateCompilationUnit(val workspaceFile: IFile) extends Interactive
override def getContents: Array[Char] = {
withSourceFile({ (sourceFile, compiler) =>
sourceFile.content
- })()
+ })(null)
}
/** Return contents of template file
@@ -116,61 +114,46 @@ case class TemplateCompilationUnit(val workspaceFile: IFile) extends Interactive
}
override def withSourceFile[T](op: (SourceFile, ScalaPresentationCompiler) => T)(orElse: => T = scalaProject.defaultOrElse): T = {
- playProject.withSourceFile(this)(op)
- }
-
- def clearBuildErrors(): Unit = {
- workspaceFile.deleteMarkers(PlayPlugin.ProblemMarkerId, true, IResource.DEPTH_INFINITE)
- }
-
- def reportBuildError(errorMsg: String, start: Int, end: Int, line: Int): Unit = {
- reportBuildError(errorMsg, new Position(start, end - start + 1), line)
- }
-
- def reportBuildError(errorMsg: String, position: Position, line: Int): Unit = {
- def positionConvertor(position: Position, line: Int) = {
- MarkerFactory.RegionPosition(position.offset, position.length, line)
- }
- val pos = positionConvertor(position, line)
- TemplateProblemMarker.create(workspaceFile, IMarker.SEVERITY_ERROR, errorMsg, pos)
+ playProject.withSourceFile(this)(op) getOrElse (orElse)
}
/** maps a region in template file into generated scala file
*/
- def mapTemplateToScalaRegion(region: IRegion) = {
- synchronized {
- val offset = mapTemplateToScalaOffset(region.getOffset())
- val end = mapTemplateToScalaOffset(region.getOffset() + region.getLength() - 1)
- new Region(offset, end - offset + 1)
- }
+ def mapTemplateToScalaRegion(region: IRegion): Option[IRegion] = synchronized {
+ for {
+ start <- mapTemplateToScalaOffset(region.getOffset())
+ end <- mapTemplateToScalaOffset(region.getOffset() + region.getLength() - 1)
+ } yield new Region(start, end - start + 1)
}
/** maps an offset in template file into generated scala file
*/
- def mapTemplateToScalaOffset(offset: Int) = {
- playProject.withPresentationCompiler { pc =>
- val gen = generatedSource()
- PositionHelper.mapSourcePosition(gen.matrix, offset)
+ def mapTemplateToScalaOffset(offset: Int): Option[Int] = synchronized {
+ for(genSource <- generatedSource().toOption) yield {
+ playProject.withPresentationCompiler { pc =>
+ PositionHelper.mapSourcePosition(genSource.matrix, offset)
+ }
}
}
/** Return the offset in the template file, given an offset in the generated source file.
* It is the inverse of `mapTemplateToScalaOffset`. */
- def templateOffset(generatedOffset: Int): Int = {
- generatedSource().mapPosition(generatedOffset)
+ def templateOffset(generatedOffset: Int): Option[Int] = synchronized {
+ generatedSource().toOption.map(_.mapPosition(generatedOffset))
}
-
- private var cachedGenerated = generatedSource()
+ /* guarded by `this`*/
+ private var cachedGenerated: Try[GeneratedSourceVirtual] = generatedSource()
+ /* guarded by `this`*/
private var oldContents = getTemplateContents
/** Returns generated source of the given compilation unit.
*
* It caches results in order to save on (relatively expensive) calls to the template compiler.
*/
- def generatedSource(): GeneratedSourceVirtual = {
- if (oldContents != getTemplateContents) synchronized {
+ def generatedSource(): Try[GeneratedSourceVirtual] = synchronized {
+ if (oldContents != getTemplateContents) {
oldContents = getTemplateContents
- println("[generating template] " + getTemplateFullPath)
+ logger.debug("[generating template] " + getTemplateFullPath)
cachedGenerated = CompilerUsing.compileTemplateToScalaVirtual(getTemplateContents.toString(), file.file, playProject)
}
cachedGenerated
@@ -179,13 +162,11 @@ case class TemplateCompilationUnit(val workspaceFile: IFile) extends Interactive
/** updates template virtual file
*/
def updateTemplateSourceFile() = {
- new PrintStream(templateSourceFile.output).print(document.get.get)
+ new PrintStream(templateSourceFile.output).print(document.map(_.get))
}
}
-object TemplateProblemMarker extends MarkerFactory(PlayPlugin.ProblemMarkerId)
-
object TemplateCompilationUnit {
private def fromEditorInput(editorInput: IEditorInput): TemplateCompilationUnit = TemplateCompilationUnit(getFile(editorInput))
55 org.scala-ide.play2/src/org/scalaide/play2/templateeditor/TemplateEditor.scala
View
@@ -1,32 +1,24 @@
package org.scalaide.play2.templateeditor
+import scala.collection.JavaConverters
+import scala.tools.eclipse.ISourceViewerEditor
+import scala.tools.eclipse.InteractiveCompilationUnit
+import scala.tools.eclipse.ui.InteractiveCompilationUnitEditor
import scala.tools.eclipse.util.SWTUtils.fnToPropertyChangeListener
-import org.eclipse.jdt.internal.ui.text.java.hover.SourceViewerInformationControl
-import org.eclipse.jface.preference.IPreferenceStore
-import org.eclipse.jface.text.IInformationControlCreator
-import org.eclipse.jface.text.source.IOverviewRuler
-import org.eclipse.jface.text.source.IVerticalRuler
-import org.eclipse.jface.text.source.projection.ProjectionSupport
-import org.eclipse.jface.text.source.projection.ProjectionViewer
+
+import org.eclipse.jdt.core.compiler.IProblem
+import org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitDocumentProvider.ProblemAnnotation
+import org.eclipse.jface.text.Position
+import org.eclipse.jface.text.source.IAnnotationModel
+import org.eclipse.jface.text.source.IAnnotationModelExtension
+import org.eclipse.jface.text.source.IAnnotationModelExtension2
+import org.eclipse.jface.text.source.ISourceViewer
import org.eclipse.jface.util.IPropertyChangeListener
import org.eclipse.jface.util.PropertyChangeEvent
-import org.eclipse.swt.SWT
-import org.eclipse.swt.layout.FillLayout
-import org.eclipse.swt.layout.GridData
-import org.eclipse.swt.layout.GridLayout
-import org.eclipse.swt.widgets.Composite
-import org.eclipse.swt.widgets.Shell
import org.eclipse.ui.editors.text.EditorsUI
import org.eclipse.ui.editors.text.TextEditor
-import org.eclipse.ui.texteditor.AnnotationPreference
-import org.eclipse.ui.texteditor.MarkerAnnotationPreferences
-import org.scalaide.play2.PlayPlugin
-import scala.tools.eclipse.ISourceViewerEditor
-import org.eclipse.jface.text.source.ISourceViewer
import org.eclipse.ui.texteditor.ChainedPreferenceStore
-import org.eclipse.jdt.internal.ui.JavaPlugin
-import scala.tools.eclipse.ui.InteractiveCompilationUnitEditor
-import scala.tools.eclipse.InteractiveCompilationUnit
+import org.scalaide.play2.PlayPlugin
class TemplateEditor extends TextEditor with ISourceViewerEditor with InteractiveCompilationUnitEditor {
private lazy val preferenceStore = new ChainedPreferenceStore(Array((EditorsUI.getPreferenceStore()), PlayPlugin.prefStore))
@@ -38,7 +30,7 @@ class TemplateEditor extends TextEditor with ISourceViewerEditor with Interactiv
setDocumentProvider(documentProvider);
override def dispose() = {
- super.dispose();
+ super.dispose()
PlayPlugin.prefStore.removePropertyChangeListener(preferenceListener)
}
@@ -59,4 +51,23 @@ class TemplateEditor extends TextEditor with ISourceViewerEditor with Interactiv
override def getViewer: ISourceViewer = getSourceViewer
override def getInteractiveCompilationUnit(): InteractiveCompilationUnit = TemplateCompilationUnit.fromEditor(this)
+
+ @volatile
+ private var previousAnnotations: List[ProblemAnnotation] = Nil
+
+ private type IAnnotationModelExtended = IAnnotationModel with IAnnotationModelExtension with IAnnotationModelExtension2
+
+ /** Return the annotation model associated with the current document. */
+ private def annotationModel: IAnnotationModelExtended = getDocumentProvider.getAnnotationModel(getEditorInput).asInstanceOf[IAnnotationModelExtended]
+
+ def updateErrorAnnotations(errors: List[IProblem]) {
+ import scala.collection.JavaConverters._
+
+ def position(p: IProblem) = new Position(p.getSourceStart, p.getSourceEnd - p.getSourceStart + 1)
+
+ val newAnnotations = for (e <- errors) yield { (new ProblemAnnotation(e, null), position(e)) }
+
+ annotationModel.replaceAnnotations(previousAnnotations.toArray, newAnnotations.toMap.asJava)
+ previousAnnotations = newAnnotations.unzip._1
+ }
}
57 org.scala-ide.play2/src/org/scalaide/play2/templateeditor/compiler/CompilerUsing.scala
View
@@ -1,44 +1,45 @@
package org.scalaide.play2.templateeditor.compiler
+import java.io.File
+import scala.util.Failure
+import scala.util.Try
+import org.scalaide.play2.PlayProject
+import play.templates.GeneratedSourceVirtual
import play.templates.ScalaTemplateCompiler
import play.templates.ScalaTemplateCompiler._
-import java.io.File
-import play.templates.GeneratedSource
import play.templates.TemplateCompilationError
import scalax.file.Path
-import org.scalaide.play2.PlayProject
+import org.scalaide.play2.properties.PlayPreferences
+import scala.tools.eclipse.logging.HasLogger
/**
* a helper for using template compiler
*/
-object CompilerUsing {
+object CompilerUsing extends HasLogger {
val templateCompiler = ScalaTemplateCompiler
- val additionalImports = """import play.templates._
-import play.templates.TemplateMagic._
-
-
-import play.api.templates._
-import play.api.templates.PlayMagic._
+ val additionalImports = """
import models._
import controllers._
import play.api.i18n._
import play.api.mvc._
import play.api.data._
-import views.html._"""
+import views.html._
+"""
/**
* invokes compile method of template compiler and returns generated source object or
* in the case of error, returns appropriate exception
*/
- def compileTemplateToScalaVirtual(content: String, source: File, playProject: PlayProject) = {
+ def compileTemplateToScalaVirtual(content: String, source: File, playProject: PlayProject): Try[GeneratedSourceVirtual] = {
val sourcePath = playProject.sourceDir.getAbsolutePath()
if (source.getAbsolutePath().indexOf(sourcePath) == -1)
- throw new Exception("Template files must locate in '" + sourcePath + "' or its subfolders!")
- try {
- templateCompiler.compileVirtual(content, source, playProject.sourceDir, "play.api.templates.Html", "play.api.templates.HtmlFormat", additionalImports)
- } catch {
- case e @ TemplateCompilationError(source: File, message: String, line: Int, column: Int) =>
+ logger.debug(s"Template file '${source.getAbsolutePath}' must be located in '$sourcePath' or one of its subfolders!")
+
+ Try {
+ templateCompiler.compileVirtual(content, source, playProject.sourceDir, "play.api.templates.Html", "play.api.templates.HtmlFormat", additionalImports + playProject.cachedPreferenceStore.getString(PlayPreferences.TemplateImports))
+ } recoverWith {
+ case TemplateCompilationError(source, message, line, column) =>
val offset = PositionHelper.convertLineColumnToOffset(content, line, column)
- throw new TemplateToScalaCompilationError(source, message, offset, line, column)
+ Failure(TemplateToScalaCompilationError(source, message, offset, line, column))
}
}
@@ -46,6 +47,24 @@ import views.html._"""
case class TemplateToScalaCompilationError(source: File, message: String, offset: Int, line: Int, column: Int) extends RuntimeException(message) {
override def toString = source.getName + ": " + message + offset + " " + line + "." + column
+
+ import org.eclipse.jdt.core.compiler.IProblem
+ import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities
+ import org.eclipse.jdt.internal.compiler.problem.DefaultProblem
+
+ def toProblem: IProblem = {
+ val severityLevel = ProblemSeverities.Error
+ new DefaultProblem(
+ source.getAbsolutePath().toCharArray,
+ message,
+ 0,
+ Array.empty[String],
+ severityLevel,
+ offset - 1,
+ offset - 1,
+ line,
+ column)
+ }
}
object PositionHelper {
@@ -77,4 +96,4 @@ object PositionHelper {
}
}
}
-}
+}
118 org.scala-ide.play2/src/org/scalaide/play2/templateeditor/compiler/TemplatePresentationCompiler.scala
View
@@ -20,10 +20,14 @@ import scala.tools.eclipse.util.EclipseFile
import scala.tools.eclipse.util.EclipseResource
import scala.tools.eclipse.ScalaPresentationCompiler
import play.templates.GeneratedSourceVirtual
+import scala.tools.eclipse.logging.HasLogger
+import scala.util.Failure
+import scala.util.Success
+import scala.util.Try
/**
* presentation compiler for template files
*/
-class TemplatePresentationCompiler(playProject: PlayProject) {
+class TemplatePresentationCompiler(playProject: PlayProject) extends HasLogger {
/**
* A map between compilation units and associated batch source files
*/
@@ -33,7 +37,7 @@ class TemplatePresentationCompiler(playProject: PlayProject) {
* Returns scala batch source file (which is a virtual file) associated to
* the given generated source.
*/
- def scalaFileFromGen(gen: GeneratedSourceVirtual) = {
+ def scalaFileFromGen(gen: GeneratedSourceVirtual): BatchSourceFile = {
val fileName = gen.path
val file = ScalaFileManager.scalaFile(fileName)
new BatchSourceFile(file, gen.content)
@@ -43,68 +47,57 @@ class TemplatePresentationCompiler(playProject: PlayProject) {
* Returns scala batch source file (which is a virtual file) which is
* the result of compiling the given template compilation unit
*/
- def scalaFileFromTCU(tcu: TemplateCompilationUnit) = {
- val gen = tcu.generatedSource()
- scalaFileFromGen(gen)
+ def scalaFileFromTCU(tcu: TemplateCompilationUnit): Try[BatchSourceFile] = {
+ tcu.generatedSource() map scalaFileFromGen
}
private val scalaProject = playProject.scalaProject
def problemsOf(tcu: TemplateCompilationUnit): List[IProblem] = {
- try {
- val gen = tcu.generatedSource()
- val src = scalaFileFromGen(gen)
- val problems = scalaProject.withPresentationCompiler(pc => pc.problemsOf(src.file))()
- def mapOffset(offset: Int) = gen.mapPosition(offset)
- def mapLine(line: Int) = gen.mapLine(line)
- problems map (p => p match {
- // problems of the generated scala file
- case problem: DefaultProblem => new DefaultProblem(
- tcu.getTemplateFullPath.toCharArray(),
- problem.getMessage(),
- problem.getID(),
- problem.getArguments(),
- ProblemSeverities.Error,
- mapOffset(problem.getSourceStart()),
- mapOffset(problem.getSourceEnd()),
- mapLine(problem.getSourceLineNumber()),
- 1)
- })
- } catch {
- // template file could not be compiled to scala file. So now there is only a single
- // problem which is the thrown exception
- case TemplateToScalaCompilationError(source, message, offset, line, column) => {
- val severityLevel = ProblemSeverities.Error
- val p = new DefaultProblem(
- source.getAbsolutePath().toCharArray,
- message,
- 0,
- new Array[String](0),
- severityLevel,
- offset - 1,
- offset - 1,
- line,
- column)
- List(p)
- }
- // any other exception will be shown at first character of document
- case e: Exception => {
- val severityLevel = ProblemSeverities.Error
- val message = e.getMessage()
- val p = new DefaultProblem(
- tcu.getTemplateFullPath.toCharArray(),
- message,
- 0,
- new Array[String](0),
- severityLevel,
- 0,
- 1,
- 1,
- 1)
- List(p)
- }
+ tcu.generatedSource() match {
+ case Success(generatedSource) =>
+ val src = scalaFileFromGen(generatedSource)
+ val problems = scalaProject.withPresentationCompiler(pc => pc.problemsOf(src.file))()
+ def mapOffset(offset: Int) = generatedSource.mapPosition(offset)
+ def mapLine(line: Int) = generatedSource.mapLine(line)
+ problems map (p => p match {
+ // problems of the generated scala file
+ case problem: DefaultProblem => new DefaultProblem(
+ tcu.getTemplateFullPath.toCharArray(),
+ problem.getMessage(),
+ problem.getID(),
+ problem.getArguments(),
+ ProblemSeverities.Error,
+ mapOffset(problem.getSourceStart()),
+ mapOffset(problem.getSourceEnd()),
+ mapLine(problem.getSourceLineNumber()),
+ 1)
+ })
+
+ case Failure(parseError: TemplateToScalaCompilationError) =>
+ List(parseError.toProblem)
+
+ case Failure(error) =>
+ logger.error(s"Unexpected error while parsing template ${tcu.file.name}", error)
+ List(unknownError(tcu, error))
}
}
+
+ private def unknownError(tcu: TemplateCompilationUnit, error: Throwable): IProblem = {
+ val severityLevel = ProblemSeverities.Error
+ val message = error.getMessage()
+ new DefaultProblem(
+ tcu.getTemplateFullPath.toCharArray(),
+ message,
+ 0,
+ Array.empty[String],
+ severityLevel,
+ 0,
+ 1,
+ 1,
+ 1)
+ }
+
def askReload(tcu: TemplateCompilationUnit, content: Array[Char]) {
sourceFiles.get(tcu) match {
@@ -119,9 +112,8 @@ class TemplatePresentationCompiler(playProject: PlayProject) {
sourceFiles.put(tcu, tcu.batchSourceFile(content))
}
}
- try {
- val gen = tcu.generatedSource()
- val src = scalaFileFromGen(gen)
+ for(generatedSource <- tcu.generatedSource()) {
+ val src = scalaFileFromGen(generatedSource)
val sourceList = List(src)
scalaProject.withPresentationCompiler(pc => {
pc.withResponse((response: pc.Response[Unit]) => {
@@ -129,14 +121,12 @@ class TemplatePresentationCompiler(playProject: PlayProject) {
response.get
})
})()
- } catch {
- case _ =>
}
}
- def withSourceFile[T](tcu: TemplateCompilationUnit)(op: (SourceFile, ScalaPresentationCompiler) => T): T =
+ def withSourceFile[T](tcu: TemplateCompilationUnit)(op: (SourceFile, ScalaPresentationCompiler) => T): Option[T] =
scalaProject.withPresentationCompiler(pc => {
- op(scalaFileFromTCU(tcu), pc)
+ scalaFileFromTCU(tcu).map(op(_, pc)).toOption
})()
def destroy() = {
26 org.scala-ide.play2/src/org/scalaide/play2/templateeditor/completion/CompletionProposalComputer.scala
View
@@ -36,17 +36,21 @@ class CompletionProposalComputer(textEditor: ITextEditor) extends ScalaCompletio
private def findCompletions(viewer: ITextViewer, position: Int, tcu: TemplateCompilationUnit)(sourceFile: SourceFile, compiler: ScalaPresentationCompiler): List[ICompletionProposal] = {
val region = ScalaWordFinder.findCompletionPoint(tcu.getTemplateContents, position)
- val mappedRegion = tcu.mapTemplateToScalaRegion(region.asInstanceOf[Region])
- val mappedPosition = tcu.mapTemplateToScalaOffset(position - 1) + 1
-
- val res = findCompletions(mappedRegion)(mappedPosition, tcu)(sourceFile, compiler).sortBy(_.relevance).reverse
-
- res.map(prop => {
- val newProp = prop.copy(startPos = prop.startPos - mappedPosition + position)
-
- ScalaCompletionProposal(viewer.getSelectionProvider)(newProp)
- })
-
+
+ val completions = {
+ for {
+ mappedRegion <- tcu.mapTemplateToScalaRegion(region)
+ mappedPosition <- tcu.mapTemplateToScalaOffset(position - 1)
+ realPosition = mappedPosition + 1
+ } yield {
+ findCompletions(mappedRegion)(realPosition, tcu)(sourceFile, compiler).sortBy(_.relevance).reverse map { prop =>
+ val newProp = prop.copy(startPos = prop.startPos - realPosition + position)
+ ScalaCompletionProposal(viewer.getSelectionProvider)(newProp)
+ }
+ }
+ }
+
+ completions getOrElse Nil
}
def computeContextInformation(viewer: ITextViewer, offset: Int): Array[IContextInformation] = {
6 org.scala-ide.play2/src/org/scalaide/play2/templateeditor/hover/TemplateHover.scala
View
@@ -13,8 +13,10 @@ class TemplateHover(tcu: TemplateCompilationUnit) extends ScalaHover(tcu) {
override def getHoverInfo(viewer: ITextViewer, region: IRegion): String = {
// maps the region to scala generated source
- val mappedRegion = tcu.mapTemplateToScalaRegion(region.asInstanceOf[Region])
- super.getHoverInfo(viewer, mappedRegion)
+ tcu.mapTemplateToScalaRegion(region) match {
+ case Some(mappedRegion) => super.getHoverInfo(viewer, mappedRegion)
+ case None => null
+ }
}
}
49 org.scala-ide.play2/src/org/scalaide/play2/templateeditor/hyperlink/LocalTemplateHyperlinkComputer.scala
View
@@ -37,27 +37,36 @@ class LocalTemplateHyperlinkComputer extends AbstractHyperlinkDetector {
return Nil
val wordRegion = ScalaWordFinder.findWord(doc.get, currentSelection.getOffset).asInstanceOf[IRegion]
- val mappedRegion = icu.mapTemplateToScalaRegion(wordRegion)
- icu.withSourceFile { (source, compiler) =>
- import compiler._
- def localSymbol(sym: compiler.Symbol): Boolean = (
- (sym ne null) &&
- (sym ne NoSymbol) &&
- sym.pos.isDefined &&
- sym.pos.source == source)
+ icu.mapTemplateToScalaRegion(wordRegion) match {
+ case Some(mappedRegion) =>
+ icu.withSourceFile { (source, compiler) =>
+ import compiler._
+ def localSymbol(sym: compiler.Symbol): Boolean = {
+ (sym ne null) &&
+ (sym ne NoSymbol) &&
+ sym.pos.isDefined &&
+ sym.pos.source == source
+ }
- val pos = compiler.rangePos(source, mappedRegion.getOffset(), mappedRegion.getOffset(), mappedRegion.getOffset() + mappedRegion.getLength())
- val response = new Response[Tree]
- compiler.askTypeAt(pos, response)
- response.get match {
- case Left(tree: Tree) if localSymbol(tree.symbol) =>
- val sym = tree.symbol
- val offset = icu.templateOffset(sym.pos.startOrPoint)
- val hyper = Hyperlink.withText(sym.name.toString)(icu, offset, sym.name.length, sym.kindString + sym.nameString, wordRegion)
- List(hyper)
- case _ => Nil
- }
- }(Nil)
+ val pos = compiler.rangePos(source, mappedRegion.getOffset(), mappedRegion.getOffset(), mappedRegion.getOffset() + mappedRegion.getLength())
+ val response = new Response[Tree]
+ compiler.askTypeAt(pos, response)
+ response.get match {
+ case Left(tree: Tree) if localSymbol(tree.symbol) =>
+ val sym = tree.symbol
+ icu.templateOffset(sym.pos.startOrPoint) match {
+ case Some(offset) =>
+ val hyper = Hyperlink.withText(sym.name.toString)(icu, offset, sym.name.length, sym.kindString + sym.nameString, wordRegion)
+ List(hyper)
+ case None =>
+ Nil
+ }
+ case _ => Nil
+ }
+ }(Nil)
+
+ case None => Nil
+ }
}
if (textEditor == null) null // can be null if generated through ScalaPreviewerFactory
12 ...ala-ide.play2/src/org/scalaide/play2/templateeditor/hyperlink/TemplateDeclarationHyperlinkDetector.scala
View
@@ -21,6 +21,7 @@ import org.eclipse.jface.text.Region
import org.scalaide.play2.templateeditor.compiler.PositionHelper
import org.scalaide.play2.templateeditor.TemplateCompilationUnit
import scala.tools.eclipse.hyperlink.text.detector.DeclarationHyperlinkDetector
+import scala.tools.eclipse.util.Utils
class TemplateDeclarationHyperlinkDetector extends DeclarationHyperlinkDetector {
@@ -32,10 +33,15 @@ class TemplateDeclarationHyperlinkDetector extends DeclarationHyperlinkDetector
}
if (doc.getChar(currentSelection.getOffset()) == '.') // otherwise it will generate an error
return Nil
- val wordRegion = ScalaWordFinder.findWord(doc.get, currentSelection.getOffset).asInstanceOf[Region]
- val mappedRegion = icu.asInstanceOf[TemplateCompilationUnit].mapTemplateToScalaRegion(wordRegion)
+ val wordRegion = ScalaWordFinder.findWord(doc.get, currentSelection.getOffset)
+
+ import Utils.any2optionable
+ val tu = icu.asInstanceOfOpt[TemplateCompilationUnit]
- super.findHyperlinks(textEditor, icu, wordRegion, mappedRegion)
+ tu.flatMap(_.mapTemplateToScalaRegion(wordRegion)) match {
+ case Some(mappedRegion) => super.findHyperlinks(textEditor, icu, wordRegion, mappedRegion)
+ case None => Nil
+ }
}
}
55 org.scala-ide.play2/src/org/scalaide/play2/templateeditor/reconciler/TemplateReconcilingStrategy.scala
View
@@ -1,72 +1,34 @@
-package org.scalaide.play2.templateeditor
-package reconciler
+package org.scalaide.play2.templateeditor.reconciler
import scala.tools.eclipse.logging.HasLogger
-import org.eclipse.core.resources.IMarker
-import org.eclipse.jdt.core.IJavaModelMarker
-import org.eclipse.jdt.core.compiler.IProblem
-import org.eclipse.jdt.internal.core.builder.JavaBuilder
-import org.eclipse.jdt.internal.ui.javaeditor.JavaMarkerAnnotation
+
import org.eclipse.jface.text.DocumentEvent
import org.eclipse.jface.text.IDocument
import org.eclipse.jface.text.IDocumentListener
import org.eclipse.jface.text.IRegion
-import org.eclipse.jface.text.Position
import org.eclipse.jface.text.reconciler.DirtyRegion
import org.eclipse.jface.text.reconciler.IReconcilingStrategy
-import org.eclipse.ui.IFileEditorInput
-import org.eclipse.ui.texteditor.ITextEditor
-import org.eclipse.ui.texteditor.MarkerAnnotation
import org.scalaide.play2.templateeditor.TemplateCompilationUnit
-import org.scalaide.play2.PlayPlugin
-import org.eclipse.ui.texteditor.SimpleMarkerAnnotation
-import org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitDocumentProvider.ProblemAnnotation
+import org.scalaide.play2.templateeditor.TemplateEditor
-class TemplateReconcilingStrategy(textEditor: /*ITextEditor*/ TemplateEditor) extends IReconcilingStrategy with HasLogger {
+class TemplateReconcilingStrategy(textEditor: TemplateEditor) extends IReconcilingStrategy with HasLogger {
private var document: IDocument = _
- private lazy val annotationModel = textEditor.getDocumentProvider.getAnnotationModel(textEditor.getEditorInput)
private lazy val templateUnit = TemplateCompilationUnit.fromEditor(textEditor)
- def setDocument(doc: IDocument) {
+ override def setDocument(doc: IDocument) {
document = doc
doc.addDocumentListener(reloader)
}
- def reconcile(dirtyRegion: DirtyRegion, subRegion: IRegion) {
+ override def reconcile(dirtyRegion: DirtyRegion, subRegion: IRegion) {
logger.debug("Incremental reconciliation not implemented.")
}
- def reconcile(partition: IRegion) {
+ override def reconcile(partition: IRegion) {
val errors = templateUnit.reconcile(document.get)
-
- updateErrorAnnotations(errors)
- }
-
- private var previousAnnotations = List[ProblemAnnotation]()
-
- def createMarkerAnnotation(problem: IProblem) {
- templateUnit.reportBuildError(problem.getMessage(), problem.getSourceStart(), problem.getSourceEnd(), problem.getSourceLineNumber())
- }
-
- private def updateErrorAnnotations(errors: List[IProblem]) {
- def position(p: IProblem) = new Position(p.getSourceStart, p.getSourceEnd - p.getSourceStart + 1)
-
- annotationModel.connect(document)
- previousAnnotations.foreach(annotationModel.removeAnnotation _)
- templateUnit.clearBuildErrors
-
- for (e <- errors) {
- createMarkerAnnotation(e)
- val annotation = new ProblemAnnotation(e, null) {
- setQuickFixable(true)
- }
- annotationModel.addAnnotation(annotation, position(e))
-
- previousAnnotations ::= annotation
- }
- annotationModel.disconnect(document)
+ textEditor.updateErrorAnnotations(errors)
}
/**
@@ -84,6 +46,5 @@ class TemplateReconcilingStrategy(textEditor: /*ITextEditor*/ TemplateEditor) ex
}
def documentAboutToBeChanged(event: DocumentEvent) {}
-
}
}
36 org.scala-ide.play2/src/org/scalaide/play2/util/Play2PropertyTester.scala
View
@@ -0,0 +1,36 @@
+package org.scalaide.play2.util
+
+import org.eclipse.core.expressions.PropertyTester
+import org.eclipse.core.resources.IProject
+import org.scalaide.play2.PlayPlugin
+import org.eclipse.jdt.core.IJavaProject
+
+object Play2PropertyTester {
+ final val IsPlayProject = "isPlay2Project"
+}
+
+/** Eclipse property tester. Can check if a project is a play2 project.
+ */
+class Play2PropertyTester() extends PropertyTester {
+
+ // from IPropertyTester
+
+ override def test(receiver: Any, property: String, args: Array[Object], expectedValue: Any): Boolean = {
+ import Play2PropertyTester._
+
+ property match {
+ case IsPlayProject =>
+ receiver match {
+ case project: IProject =>
+ PlayPlugin.plugin.asPlayProject(project).isDefined
+ case project: IJavaProject =>
+ PlayPlugin.plugin.asPlayProject(project.getProject()).isDefined
+ case _ =>
+ false
+ }
+ case _ =>
+ false
+ }
+ }
+
+}
16 org.scala-ide.play2/src/org/scalaide/play2/util/SyncedScopedPreferenceStore.scala
View
@@ -0,0 +1,16 @@
+package org.scalaide.play2.util
+
+import org.eclipse.core.resources.IProject
+import org.eclipse.core.resources.ProjectScope
+import org.eclipse.ui.preferences.ScopedPreferenceStore
+
+class SyncedScopedPreferenceStore(project: IProject, pluginId: String) {
+
+ private val preferenceStore = new ScopedPreferenceStore(new ProjectScope(project), pluginId)
+
+ def getString(name: String): String = {
+ preferenceStore.synchronized {
+ preferenceStore.getString(name)
+ }
+ }
+}
91 pom.xml
View
@@ -29,7 +29,7 @@
<repo.scala-ide.root>http://download.scala-ide.org</repo.scala-ide.root>
<!-- fixed versions -->
- <tycho.version>0.15.0</tycho.version>
+ <tycho.version>0.16.0</tycho.version>
<scala.plugin.version>3.1.0</scala.plugin.version>
<junit.version>4.10</junit.version>
@@ -45,24 +45,25 @@
<repo.eclipse>Select an Eclipse profile !</repo.eclipse>
<repo.ajdt>Select an Eclipse profile !</repo.ajdt>
<weaving.hook.plugin.version>Select an Eclipse profile !</weaving.hook.plugin.version>
- <ecosystem-eclipse-version>Select an Eclipse profile !</ecosystem-eclipse-version>
<!-- linked to Scala version -->
- <scala.version>Select a Scala profile !</scala.version>
- <version.suffix>Select a Scala profile !</version.suffix>
- <scala.version.short>Select a Scala profile !</scala.version.short>
- <!-- play version depend on Scala version. 2.9.x -> 2.0.x, 2.10.x -> 2.1.x !-->
- <play.artifactId>Select a Scala profile !</play.artifactId>
- <play.version>Select a Scala profile !</play.version>
- <templates.artifactId>Select a Scala profile !</templates.artifactId>
- <templates.version>Select a Scala profile !</templates.version>
- <scala.io.core.artifactId>Select a Scala profile !</scala.io.core.artifactId>
- <scala.io.core.version>Select a Scala profile !</scala.io.core.version>
- <scala.io.file.artifactId>Select a Scala profile !</scala.io.file.artifactId>
- <scala.io.file.version>Select a Scala profile !</scala.io.file.version>
- <scala.arm.groupId>Select a Scala profile !</scala.arm.groupId>
- <scala.arm.artifactId>Select a Scala profile !</scala.arm.artifactId>
- <scala.arm.version>Select a Scala profile !</scala.arm.version>
+ <scala.version>2.10.1</scala.version>
+ <version.suffix>2_10</version.suffix>
+ <scala.version.short>2.10</scala.version.short>
+ <ecosystem-scala-version>210</ecosystem-scala-version>
+
+ <!-- play version depend on Scala version. 2.9.x -> 2.0.x, 2.10.x -> 2.1.x !-->
+ <play.artifactId>play_2.10</play.artifactId>
+ <play.version>2.1.0</play.version>
+ <templates.artifactId>templates_2.10</templates.artifactId>
+ <templates.version>2.1.0</templates.version>
+ <scala.io.core.artifactId>scala-io-core_2.10</scala.io.core.artifactId>
+ <scala.io.core.version>0.4.2</scala.io.core.version>
+ <scala.io.file.artifactId>scala-io-file_2.10</scala.io.file.artifactId>
+ <scala.io.file.version>0.4.2</scala.io.file.version>
+ <scala.arm.groupId>com.jsuereth</scala.arm.groupId>
+ <scala.arm.artifactId>scala-arm_2.10</scala.arm.artifactId>
+ <scala.arm.version>1.3</scala.arm.version>
<!-- linked to Scala IDE version -->
<repo.scala-ide>Select a Scala IDE profile !</repo.scala-ide>
@@ -97,50 +98,6 @@
</profile>
<profile>
- <id>scala-2.9.x</id>
- <properties>
- <scala.version>2.9.3-RC2</scala.version>
- <version.suffix>2_09</version.suffix>
- <scala.version.short>2.9</scala.version.short>
- <ecosystem-scala-version>29</ecosystem-scala-version>
-
- <play.artifactId>play_2.9.2</play.artifactId>
- <play.version>2.1-09142012</play.version>
- <templates.artifactId>templates_2.9.2</templates.artifactId>
- <templates.version>2.1-09142012</templates.version>
- <scala.io.core.artifactId>scala-io-core_2.9.2</scala.io.core.artifactId>
- <scala.io.core.version>0.4.1</scala.io.core.version>
- <scala.io.file.artifactId>scala-io-file_2.9.2</scala.io.file.artifactId>
- <scala.io.file.version>0.4.1</scala.io.file.version>
- <scala.arm.groupId>com.github.jsuereth.scala-arm</scala.arm.groupId>
- <scala.arm.artifactId>scala-arm_2.9.1</scala.arm.artifactId>
- <scala.arm.version>1.1</scala.arm.version>
- </properties>
- </profile>
-
- <profile>
- <id>scala-2.10.x</id>
- <properties>
- <scala.version>2.10.1-RC2</scala.version>
- <version.suffix>2_10</version.suffix>
- <scala.version.short>2.10</scala.version.short>
- <ecosystem-scala-version>210</ecosystem-scala-version>
-
- <play.artifactId>play_2.10</play.artifactId>
- <play.version>2.1.0</play.version>
- <templates.artifactId>templates_2.10</templates.artifactId>
- <templates.version>2.1.0</templates.version>
- <scala.io.core.artifactId>scala-io-core_2.10</scala.io.core.artifactId>
- <scala.io.core.version>0.4.2</scala.io.core.version>
- <scala.io.file.artifactId>scala-io-file_2.10</scala.io.file.artifactId>
- <scala.io.file.version>0.4.2</scala.io.file.version>
- <scala.arm.groupId>com.jsuereth</scala.arm.groupId>
- <scala.arm.artifactId>scala-arm_2.10</scala.arm.artifactId>
- <scala.arm.version>1.3</scala.arm.version>
- </properties>
- </profile>
-
- <profile>
<id>scala-ide-nightly</id>
<properties>
<repo.scala-ide>${repo.scala-ide.root}/nightly-scala-ide-${nightly-eclipse-version}-${ecosystem-scala-version}x</repo.scala-ide>
@@ -155,7 +112,7 @@
</profile>
<profile>
- <id>scala-ide-stable (not available yet)</id>
+ <id>scala-ide-stable</id>
<properties>
<repo.scala-ide>${repo.scala-ide.root}/sdk/${ecosystem-eclipse-version}/scala${ecosystem-scala-version}/stable/site</repo.scala-ide>
</properties>
@@ -215,7 +172,7 @@
</execution>
</executions>
<configuration>
- <alias>typesafe</alias>
+ <alias>typesafe</alias>
</configuration>
</plugin>
</plugins>
@@ -224,9 +181,9 @@
</profiles>
<!-- scm configuration is require to extract the github hash-->
- <scm>
- <connection>scm:git://github.com/skyluc/plugin.git</connection>
- <url>https://github.com/skyluc/plugin</url>
+ <scm>
+ <connection>scm:git://github.com/skyluc/plugin.git</connection>
+ <url>https://github.com/skyluc/plugin</url>
</scm>
<dependencyManagement>
@@ -318,7 +275,7 @@
<configuration>
<useUIHarness>false</useUIHarness>
<useUIThread>false</useUIThread>
-
+
<!-- Enable JDT weaving -->
<systemProperties combine.children="append">
<aj.weaving.verbose>true</aj.weaving.verbose>

No commit comments for this range

Something went wrong with that request. Please try again.