├── .gitignore
├── CONTRIBUTING.md
├── README.md
├── build.sh
├── org.scala-ide.play2.feature
├── .project
├── build.properties
├── feature.xml
└── pom.xml
├── org.scala-ide.play2.source.feature
├── .project
├── build.properties
├── feature.xml
└── pom.xml
├── org.scala-ide.play2.templates
├── .classpath
├── .project
├── META-INF
│ └── MANIFEST.MF
├── build.properties
├── plugin.xml
├── pom.xml
└── src
│ └── org
│ └── scalaide
│ └── play2
│ └── templates
│ ├── Activator.scala
│ ├── MasterProjectionDocumentProvider.scala
│ ├── TemplateCompiler.scala
│ ├── TemplateGeneratedSource.scala
│ ├── TemplateParser.scala
│ └── TemplateProcessing.scala
├── org.scala-ide.play2.tests
├── .classpath
├── .project
├── META-INF
│ └── MANIFEST.MF
├── build.properties
├── pom.xml
├── src
│ └── org
│ │ └── scalaide
│ │ └── play2
│ │ ├── RouteTestSuite.scala
│ │ ├── TemplateTestSuite.scala
│ │ ├── TestSuite.scala
│ │ ├── indenter
│ │ └── TemplateAutoIndentTest.scala
│ │ ├── lexical
│ │ └── PlayDocumentPartitionerTests.scala
│ │ ├── quickassist
│ │ ├── ControllerMethodTest.scala
│ │ └── ResolverTest.scala
│ │ ├── routeeditor
│ │ ├── RouteActionTest.scala
│ │ ├── RouteTest.scala
│ │ ├── RouteUriTest.scala
│ │ ├── completion
│ │ │ ├── ActionContentAssistProcessorTest.scala
│ │ │ ├── CompletionComputerTest.scala
│ │ │ ├── HttpMethodCompletionComputerTest.scala
│ │ │ └── UriCompletionComputerTest.scala
│ │ ├── handlers
│ │ │ └── LocalRenameTest.scala
│ │ ├── hyperlink
│ │ │ ├── MethodFinderTest.scala
│ │ │ └── RouteHyperlinkDetectorTest.scala
│ │ └── lexical
│ │ │ ├── AbstractRouteScannerTest.scala
│ │ │ ├── RouteActionScannerTest.scala
│ │ │ ├── RoutePartitionTokeniserTest.scala
│ │ │ └── RouteURIScannerTest.scala
│ │ └── templateeditor
│ │ ├── BeforeAfterTemplateVersion.scala
│ │ ├── lexical
│ │ ├── TemplateCompilationUnitTest.scala
│ │ └── TemplatePartitionTokniserTest.scala
│ │ └── sse
│ │ ├── TemplateContentDescriberTest.scala
│ │ └── lexical
│ │ └── TemplateRegionParserTest.scala
└── test-workspace
│ ├── .gitignore
│ ├── aProject
│ ├── .classpath
│ ├── .project
│ ├── app
│ │ └── views
│ │ │ ├── index.scala.html
│ │ │ ├── scala_compiler_error.scala.html
│ │ │ ├── template_parse_error.scala.html
│ │ │ └── template_unclosed_comment.scala.html
│ ├── moreviews
│ │ └── more.scala.html
│ ├── route
│ └── src
│ │ └── org
│ │ └── example
│ │ ├── JavaClass.java
│ │ └── ScalaClass.scala
│ ├── resolver
│ ├── .classpath
│ ├── .project
│ ├── app
│ │ └── controllers
│ │ │ ├── Application.scala
│ │ │ ├── JavaApplication.java
│ │ │ ├── JavaNonController.java
│ │ │ └── NonController.scala
│ └── src
│ │ └── play
│ │ ├── api
│ │ └── mvc
│ │ │ ├── Action.scala
│ │ │ └── EssentialAction.scala
│ │ └── mvc
│ │ ├── Controller.java
│ │ └── Result.java
│ ├── routeActionCompletions
│ ├── .classpath
│ ├── .project
│ ├── app
│ │ ├── RootScalaApplication.scala
│ │ ├── RootStaticJavaApplication.java
│ │ ├── ScalaPackage
│ │ │ └── package.scala
│ │ └── controllers
│ │ │ ├── java
│ │ │ ├── AbstractApplication.java
│ │ │ ├── Application.java
│ │ │ ├── InterfaceApplication.java
│ │ │ └── SubApplication.java
│ │ │ ├── scala
│ │ │ ├── AbstractApp.scala
│ │ │ ├── ActionWithMangledName.scala
│ │ │ ├── AppClass.scala
│ │ │ ├── AppNotExtendingController.scala
│ │ │ ├── MembersVisibility.scala
│ │ │ ├── SubAppClass.scala
│ │ │ ├── TraitApp.scala
│ │ │ └── empty
│ │ │ │ └── Empty
│ │ │ └── simple
│ │ │ └── SimpleScalaPlayApp.scala
│ └── src
│ │ └── play
│ │ ├── api
│ │ └── mvc
│ │ │ ├── Action.scala
│ │ │ └── EssentialAction.scala
│ │ └── mvc
│ │ ├── Controller.java
│ │ └── Result.java
│ └── routeHyperlink
│ ├── .classpath
│ ├── .project
│ └── app
│ ├── controllers
│ ├── JavaApplication.java
│ └── ScalaApplication.scala
│ └── model
│ └── Element.scala
├── org.scala-ide.play2.update-site
├── .project
├── pom.xml
└── site.xml
├── org.scala-ide.play2
├── .classpath
├── .project
├── META-INF
│ └── MANIFEST.MF
├── about.ini
├── about.png
├── build.properties
├── icons
│ ├── newtemplate.png
│ ├── pin.png
│ ├── play.png
│ ├── routes.png
│ ├── sample.gif
│ └── web.png
├── plugin.properties
├── plugin.xml
├── pom.xml
├── schema
│ └── template.processing.exsd
└── src
│ └── org
│ └── scalaide
│ └── play2
│ ├── IssueTracker.scala
│ ├── PlayClassNames.scala
│ ├── PlayPlugin.scala
│ ├── PlayProject.scala
│ ├── lexical
│ ├── PlayDocumentPartitioner.scala
│ └── PlayPartitionTokeniser.scala
│ ├── properties
│ ├── PlayPreferences.scala
│ ├── PreferenceInitializer.scala
│ └── ProjectPropertyPage.scala
│ ├── quickassist
│ ├── AddRouteEntryProposal.scala
│ ├── AddRouteEntryScala.scala
│ ├── ControllerMethod.scala
│ └── ControllerMethodResolver.scala
│ ├── routeeditor
│ ├── EditorMessages.properties
│ ├── EditorMessages.scala
│ ├── HasScalaProject.scala
│ ├── RouteAction.scala
│ ├── RouteConfiguration.scala
│ ├── RouteDocumentProvider.scala
│ ├── RouteDoubleClickStrategy.scala
│ ├── RouteEditor.scala
│ ├── RoutePresentationReconciler.scala
│ ├── RouteSyntaxClasses.scala
│ ├── RouteUri.scala
│ ├── completion
│ │ ├── ActionContentAssistProcessor.scala
│ │ ├── HttpMethodsCompletionComputer.scala
│ │ ├── UriCompletionComputer.scala
│ │ └── action
│ │ │ ├── ActionCompletionComputer.scala
│ │ │ ├── ActionCompletionProposal.scala
│ │ │ ├── ActionRouteInput.scala
│ │ │ └── MembersComputer.scala
│ ├── formatter
│ │ └── RouteFormattingStrategy.scala
│ ├── handlers
│ │ ├── Format.scala
│ │ └── LocalRename.scala
│ ├── hyperlink
│ │ ├── MethodFinder.scala
│ │ ├── MethodSearchRequestor.scala
│ │ ├── RouteHyperlinkComputer.scala
│ │ └── RouteHyperlinkDetector.scala
│ ├── lexical
│ │ ├── AbstractRouteScanner.scala
│ │ ├── HTTPKeywords.scala
│ │ ├── MethodPackageRule.scala
│ │ ├── RouteActionScanner.scala
│ │ ├── RouteDocumentPartitioner.scala
│ │ ├── RoutePartitionTokeniser.scala
│ │ ├── RoutePartitions.scala
│ │ └── RouteURIScanner.scala
│ └── properties
│ │ ├── RouteColorPreferenceInitializer.scala
│ │ ├── RouteFormatterPreferencePage.scala
│ │ ├── RoutePreviewerFactoryConfiguration.scala
│ │ └── RouteSyntaxColoringPreferencePage.scala
│ ├── templateeditor
│ ├── BracketAutoEditStrategy.scala
│ ├── TemplateAutoIndentStrategy.scala
│ ├── TemplateCompilationUnit.scala
│ ├── TemplateConfiguration.scala
│ ├── TemplateDocumentProvider.scala
│ ├── TemplateEditor.scala
│ ├── TemplateSyntaxClasses.scala
│ ├── compiler
│ │ └── CompilerUsing.scala
│ ├── completion
│ │ └── CompletionProposalComputer.scala
│ ├── hyperlink
│ │ ├── LocalTemplateHyperlinkComputer.scala
│ │ └── TemplateDeclarationHyperlinkDetector.scala
│ ├── lexical
│ │ ├── HtmlTagScanner.scala
│ │ ├── TemplateDefaultScanner.scala
│ │ ├── TemplateDocumentPartitioner.scala
│ │ ├── TemplateParsing.scala
│ │ ├── TemplatePartitionTokeniser.scala
│ │ └── TemplatePartitions.scala
│ ├── processing
│ │ ├── TemplateProcessing.scala
│ │ ├── TemplateProcessingProvider.scala
│ │ ├── TemplateVersionExhibitor.scala
│ │ └── TemplateVersionExtractor.scala
│ ├── properties
│ │ ├── TemplateColorPreferenceInitializer.scala
│ │ ├── TemplatePreviewerFactoryConfiguration.scala
│ │ └── TemplateSyntaxColoringPreferencePage.scala
│ ├── reconciler
│ │ └── TemplateReconcilingStrategy.scala
│ └── sse
│ │ ├── ContentTypeIdForScala.scala
│ │ ├── TemplateActionContributor.scala
│ │ ├── TemplateContentDescriber.scala
│ │ ├── TemplateStructuredEditor.scala
│ │ ├── TemplateStructuredTextViewerConfiguration.scala
│ │ ├── hyperlink
│ │ └── StructuredTemplateDeclarationHyperlinkDetector.scala
│ │ ├── lexical
│ │ ├── PartitionHelpers.scala
│ │ ├── TemplateRegionParser.scala
│ │ ├── TemplateStructuredTextPartitioner.scala
│ │ └── TemplateTextRegion.scala
│ │ ├── model
│ │ ├── TemplateAdapterFactoryProvider.scala
│ │ ├── TemplateDocumentLoader.scala
│ │ ├── TemplateModelHandler.scala
│ │ ├── TemplateStructureDocument.scala
│ │ └── TemplateStructuredModel.scala
│ │ ├── style
│ │ └── ScalaLineStyleProvider.scala
│ │ └── validation
│ │ └── ScalaSourceValidator.scala
│ ├── util
│ ├── Debugger.scala
│ ├── Images.scala
│ ├── Play2PropertyTester.scala
│ ├── StoredEditorUtils.scala
│ └── SyncedScopedPreferenceStore.scala
│ └── wizards
│ ├── NewTemplateWizard.scala
│ └── NewTemplateWizardPage.scala
└── pom.xml
/.gitignore:
--------------------------------------------------------------------------------
1 | .cache*
2 | target/
3 | .settings/
4 | .target/
5 | .worksheet/
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Scala IDE plugin for Play 2.x
2 |
3 | This is an extension to Scala IDE to support Play 2.x routes and template files.
4 |
5 | For user documentation, check the [wiki](https://github.com/scala-ide/scala-ide-play2/wiki).
6 |
7 | ## Project structure
8 |
9 | The project is composed of 5 Eclipse plugins:
10 |
11 | * the core plugin
12 | * the test plugin
13 | * an Eclipse feature
14 | * an Eclipse source feature
15 | * an Eclipse update-site
16 |
17 | The projects can be imported inside Scala IDE. And they are fully configured to be compiled with maven and tycho.
18 |
19 | ## Build
20 |
21 | Simply run the ``./build.sh`` script.
22 |
23 | The build is based on
24 | [plugin-profiles](https://github.com/scala-ide/plugin-profiles) and
25 | can be built against several versions of the IDE and Eclipse.
26 |
--------------------------------------------------------------------------------
/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | mvn -Peclipse-luna -Pscala-ide-nightly -Pscala-2.11.x clean verify
4 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.feature/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | org.scala-ide.play2.feature
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.pde.FeatureBuilder
10 |
11 |
12 |
13 |
14 |
15 | org.eclipse.pde.FeatureNature
16 |
17 |
18 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.feature/build.properties:
--------------------------------------------------------------------------------
1 | bin.includes = feature.xml
2 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.feature/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.scala-ide
7 | org.scala-ide.play2.build
8 | 0.11.0-SNAPSHOT
9 |
10 | org.scala-ide.play2.feature
11 | eclipse-feature
12 |
13 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.source.feature/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | org.scala-ide.play2.source.feature
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.pde.FeatureBuilder
10 |
11 |
12 |
13 |
14 |
15 | org.eclipse.pde.FeatureNature
16 |
17 |
18 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.source.feature/build.properties:
--------------------------------------------------------------------------------
1 | bin.includes = \
2 | feature.xml
3 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.source.feature/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 |
5 | org.scala-ide
6 | org.scala-ide.play2.build
7 | 0.11.0-SNAPSHOT
8 |
9 | org.scala-ide.play2.source.feature
10 | eclipse-feature
11 |
12 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.templates/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.templates/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | org.scala-ide.play2.templates24
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.pde.ManifestBuilder
10 |
11 |
12 |
13 |
14 | org.eclipse.pde.SchemaBuilder
15 |
16 |
17 |
18 |
19 | org.scala-ide.sdt.core.scalabuilder
20 |
21 |
22 |
23 |
24 |
25 | org.scala-ide.sdt.core.scalanature
26 | org.eclipse.pde.PluginNature
27 | org.eclipse.jdt.core.javanature
28 |
29 |
30 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.templates/META-INF/MANIFEST.MF:
--------------------------------------------------------------------------------
1 | Manifest-Version: 1.0
2 | Bundle-ManifestVersion: 2
3 | Bundle-Name: Twirl Templates for Play 2.6
4 | Bundle-SymbolicName: org.scala-ide.play2.templates;singleton:=true
5 | Bundle-Version: 0.11.0.qualifier
6 | Bundle-Activator: org.scalaide.play2.templates.Activator
7 | Require-Bundle: org.eclipse.core.runtime,
8 | org.scala-lang.scala-library;bundle-version="[2.12,2.13)",
9 | org.scala-lang.scala-compiler;bundle-version="[2.12,2.13)",
10 | org.scala-lang.scala-reflect;bundle-version="[2.12,2.13)",
11 | org.scala-lang.modules.scala-xml,
12 | org.scala-lang.modules.scala-parser-combinators,
13 | org.scala-ide.play2;bundle-version="[0.11,0.12)",
14 | org.scala-lang.scala-library
15 | Bundle-RequiredExecutionEnvironment: JavaSE-1.6
16 | Bundle-ActivationPolicy: lazy
17 | Bundle-ClassPath: .,
18 | target/lib/twirl-compiler.jar,
19 | target/lib/twirl-parser.jar
20 | Import-Package:
21 | com.ibm.icu.text;apply-aspects:=false;org.eclipse.swt.graphics;apply-aspects:=false,
22 | scala.tools.eclipse.contribution.weaving.jdt.ui.javaeditor.formatter;apply-aspects:=false,
23 | scala.tools.eclipse.contribution.weaving.jdt.ui.document;apply-aspects:=false,
24 | org.eclipse.jface.text,
25 | org.eclipse.jface.text.projection,
26 | scala.xml,
27 | scala.util.parsing.input,
28 | scala.reflect.internal.util
29 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.templates/build.properties:
--------------------------------------------------------------------------------
1 | source.. = src/
2 | output.. = target/classes
3 | bin.includes = plugin.xml,\
4 | META-INF/,\
5 | .,\
6 | *.xml,\
7 | target/lib,\
8 | target/lib/twirl-compiler.jar,\
9 | target/lib/twirl-parser.jar
10 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.templates/plugin.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
7 |
9 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.templates/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 |
4 | org.scala-ide
5 | org.scala-ide.play2.build
6 | 0.11.0-SNAPSHOT
7 |
8 | org.scala-ide.play2.templates
9 | 0.11.0-SNAPSHOT
10 | eclipse-plugin
11 |
12 |
13 |
14 | com.typesafe.play
15 | ${twirl-compiler.artifactId}
16 | ${twirl.version}
17 | sources
18 |
19 |
20 | com.typesafe.play
21 | ${twirl-parser.artifactId}
22 | ${twirl.version}
23 | sources
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | org.apache.maven.plugins
32 | maven-dependency-plugin
33 |
34 |
35 | copy
36 | initialize
37 |
38 | copy
39 |
40 |
41 |
42 |
43 | com.typesafe.play
44 | ${twirl-compiler.artifactId}
45 | twirl-compiler.jar
46 |
47 |
48 | com.typesafe.play
49 | ${twirl-parser.artifactId}
50 | twirl-parser.jar
51 |
52 |
53 | true
54 | ${project.build.directory}/lib
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.templates/src/org/scalaide/play2/templates/Activator.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.templates
2 |
3 | import org.osgi.framework.BundleActivator
4 | import org.osgi.framework.BundleContext
5 |
6 | object Activator {
7 | @volatile
8 | private var context: BundleContext = _
9 |
10 | def getContext: BundleContext = context
11 | }
12 |
13 | class Activator extends BundleActivator {
14 |
15 | override def start(bundleContext: BundleContext): Unit =
16 | Activator.context = bundleContext
17 |
18 | override def stop(bundleContext: BundleContext): Unit =
19 | Activator.context = null
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.templates/src/org/scalaide/play2/templates/MasterProjectionDocumentProvider.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.templates
2 |
3 | import scala.tools.eclipse.contribution.weaving.jdt.ui.document.IMasterProjectionDocumentProvider
4 | import org.eclipse.jface.text.IDocument
5 | import org.scalaide.play2.templateeditor.sse.model.TemplateStructuredDocument
6 |
7 | class MasterProjectionDocumentProvider extends IMasterProjectionDocumentProvider {
8 | override def extractActualMaster(master: IDocument) = master match {
9 | case master @ TemplateStructuredDocument(_, _) => master.delegate
10 | case _ => master
11 | }
12 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2.templates/src/org/scalaide/play2/templates/TemplateCompiler.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.templates
2 |
3 | import java.io.File
4 |
5 | import scala.util.Failure
6 | import scala.util.Try
7 |
8 | import org.scalaide.play2.properties.PlayPreferences
9 | import org.scalaide.play2.templateeditor.compiler.PositionHelper
10 | import org.scalaide.play2.templateeditor.compiler.TemplateToScalaCompilationError
11 | import org.scalaide.play2.templateeditor.processing.GeneratedSource
12 |
13 | import play.twirl.compiler.TemplateCompilationError
14 | import play.twirl.compiler.TwirlCompiler
15 |
16 | object TemplateCompiler {
17 | private val templateCompiler = TwirlCompiler
18 |
19 | def compile(content: String, source: File, sourceDirectory: File, additionalImports: String, inclusiveDot: Boolean): Try[GeneratedSource] =
20 | Try {
21 | templateCompiler.compileVirtual(
22 | content,
23 | source,
24 | sourceDirectory,
25 | "Html",
26 | "HtmlFormat",
27 | PlayPreferences.deserializeImports(additionalImports),
28 | inclusiveDot = inclusiveDot)
29 | } map {
30 | TemplateGeneratedSource
31 | } recoverWith {
32 | case TemplateCompilationError(source, message, line, column) =>
33 | val offset = PositionHelper.convertLineColumnToOffset(content, line, column)
34 | Failure(TemplateToScalaCompilationError(source, message, offset, line, column))
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.templates/src/org/scalaide/play2/templates/TemplateGeneratedSource.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.templates
2 |
3 | import org.scalaide.play2.templateeditor.processing.GeneratedSource
4 |
5 | import play.twirl.compiler.GeneratedSourceVirtual
6 |
7 | case class TemplateGeneratedSource(wrapped: GeneratedSourceVirtual) extends GeneratedSource {
8 | override def content: String = wrapped.content
9 | override def matrix: Seq[(Int, Int)] = wrapped.matrix
10 | override def mapPosition(generatedPosition: Int): Int = wrapped.mapPosition(generatedPosition)
11 | }
12 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.templates/src/org/scalaide/play2/templates/TemplateProcessing.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.templates
2 |
3 | import java.io.File
4 |
5 | import scala.io.Codec
6 | import scala.util.Try
7 | import scala.util.parsing.input.Positional
8 |
9 | import org.scalaide.play2.templateeditor.lexical.TemplateParsing.PlayTemplate
10 | import org.scalaide.play2.templateeditor.processing.GeneratedSource
11 | import org.scalaide.play2.templateeditor.processing.{ TemplateProcessing => PlayProcessing }
12 |
13 | class TemplateProcessing extends PlayProcessing {
14 | def compile(content: String, source: File, sourceDirectory: File, additionalImports: String, codec: Codec, inclusiveDot: Boolean): Try[GeneratedSource] =
15 | TemplateCompiler.compile(content, source, sourceDirectory, additionalImports, inclusiveDot)
16 |
17 | def parse(templateCode: String): List[PlayTemplate] = TemplateParser.parse(templateCode)
18 |
19 | def length(input: Positional): Int = TemplateParser.length(input)
20 | }
21 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | org.scala-ide.play2.tests
4 |
5 |
6 |
7 |
8 |
9 | org.scala-ide.sdt.core.scalabuilder
10 |
11 |
12 |
13 |
14 |
15 | org.scala-ide.sdt.core.scalanature
16 | org.eclipse.jdt.core.javanature
17 |
18 |
19 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/META-INF/MANIFEST.MF:
--------------------------------------------------------------------------------
1 | Manifest-Version: 1.0
2 | Bundle-ManifestVersion: 2
3 | Bundle-Name: Scala Plugin (Test)
4 | Bundle-SymbolicName: org.scala-ide.play2.tests
5 | Bundle-Version: 0.11.0.qualifier
6 | Bundle-Vendor: scala-ide.org
7 | Fragment-Host: org.scala-ide.play2
8 | Bundle-RequiredExecutionEnvironment: JavaSE-1.6
9 | Require-Bundle: org.scala-lang.scala-library,
10 | org.eclipse.equinox.weaving.aspectj,
11 | org.junit;bundle-version="4.5.0",
12 | org.scala-ide.sdt.core,
13 | org.scala-ide.play2.templates
14 | Import-Package: org.scalaide.core.testsetup,
15 | org.aspectj.weaver.loadtime.definition
16 | Bundle-ClassPath: .,
17 | target/lib/mockito-all-1.9.0.jar,
18 | target/lib/twirl-compiler.jar,
19 | target/lib/twirl-parser.jar
20 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/build.properties:
--------------------------------------------------------------------------------
1 | source.. = src/
2 | output.. = target/classes/
3 | bin.includes = META-INF/,\
4 | test-workspace/,\
5 | .
6 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 |
4 | org.scala-ide
5 | org.scala-ide.play2.build
6 | 0.11.0-SNAPSHOT
7 |
8 | org.scala-ide.play2.tests
9 | eclipse-test-plugin
10 |
11 |
12 |
13 | org.mockito
14 | mockito-all
15 |
16 |
17 | com.typesafe.play
18 | ${twirl-compiler.artifactId}
19 |
20 |
21 | com.typesafe.play
22 | ${twirl-parser.artifactId}
23 |
24 |
25 |
26 |
27 | src
28 |
29 |
30 | org.eclipse.tycho
31 | tycho-surefire-plugin
32 |
33 | ${project.artifactId}
34 | org.scalaide.play2.TestSuite
35 |
36 |
37 |
38 |
39 | org.apache.maven.plugins
40 | maven-dependency-plugin
41 |
42 |
43 | copy
44 | initialize
45 |
46 | copy
47 |
48 |
49 |
50 |
51 | org.mockito
52 | mockito-all
53 | ${project.build.directory}/lib
54 |
55 |
56 | com.typesafe.play
57 | ${twirl-compiler.artifactId}
58 | twirl-compiler.jar
59 | ${project.build.directory}/lib
60 |
61 |
62 | com.typesafe.play
63 | ${twirl-parser.artifactId}
64 | twirl-parser.jar
65 | ${project.build.directory}/lib
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/src/org/scalaide/play2/RouteTestSuite.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2
2 |
3 | import org.junit.runner.RunWith
4 | import org.junit.runners.Suite.SuiteClasses
5 | import org.scalaide.play2.routeeditor.hyperlink.RouteHyperlinkDetectorTest
6 | import org.scalaide.play2.routeeditor.hyperlink.MethodFinderTest
7 | import org.scalaide.play2.routeeditor.RouteActionTest
8 | import org.scalaide.play2.routeeditor.completion.HttpMethodCompletionComputerTest
9 | import org.scalaide.play2.routeeditor.lexical.RoutePartitionTokeniserTest
10 | import org.scalaide.play2.routeeditor.completion.UriCompletionComputerTest
11 | import org.scalaide.play2.routeeditor.handlers.LocalRenameTest
12 | import org.scalaide.play2.routeeditor.RouteUriTest
13 |
14 | @RunWith(value=classOf[org.junit.runners.Suite])
15 | @SuiteClasses(value=Array(
16 | classOf[RouteHyperlinkDetectorTest],
17 | // Test disabled from the test suite as they require UI
18 | // classOf[RouteActionScannerTest],
19 | // classOf[RouteURIScannerTest],
20 | // classOf[RouteScannerTest],
21 | classOf[MethodFinderTest],
22 | classOf[RouteActionTest],
23 | classOf[HttpMethodCompletionComputerTest],
24 | classOf[UriCompletionComputerTest],
25 | classOf[RoutePartitionTokeniserTest],
26 | classOf[LocalRenameTest],
27 | classOf[RouteUriTest]))
28 | class RouteTestSuite {
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/src/org/scalaide/play2/TemplateTestSuite.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2
2 |
3 | import org.junit.runner.RunWith
4 | import org.junit.runners.Suite.SuiteClasses
5 | import org.scalaide.play2.templateeditor.lexical.TemplatePartitionTokeniserTest
6 | import org.scalaide.play2.templateeditor.lexical.TemplateCompilationUnitTest
7 | import org.scalaide.play2.templateeditor.sse.lexical.TemplateRegionParserTest
8 | import org.scalaide.play2.indenter.TemplateAutoIndentTest
9 | import org.scalaide.play2.templateeditor.sse.TemplateContentDescriberTest
10 | @RunWith(value = classOf[org.junit.runners.Suite])
11 | @SuiteClasses(value = Array(
12 | classOf[TemplateAutoIndentTest],
13 | classOf[TemplatePartitionTokeniserTest],
14 | classOf[TemplateCompilationUnitTest],
15 | classOf[TemplateRegionParserTest],
16 | classOf[TemplateContentDescriberTest]))
17 | class TemplateTestSuite {
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/src/org/scalaide/play2/TestSuite.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2
2 |
3 | import org.junit.runner.RunWith
4 | import org.junit.runners.Suite.SuiteClasses
5 | import org.scalaide.play2.lexical.PlayDocumentPartitionerTests
6 | import org.scalaide.play2.quickassist.ControllerMethodTest
7 | import org.scalaide.play2.quickassist.ResolverTest
8 | import org.scalaide.play2.routeeditor.completion.ActionContentAssistProcessorTest
9 |
10 | @RunWith(value=classOf[org.junit.runners.Suite])
11 | @SuiteClasses(value=Array(
12 | classOf[RouteTestSuite],
13 | classOf[TemplateTestSuite],
14 | classOf[ControllerMethodTest],
15 | classOf[ActionContentAssistProcessorTest],
16 | classOf[ResolverTest],
17 | classOf[PlayDocumentPartitionerTests]
18 | ))
19 | class TestSuite
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/src/org/scalaide/play2/indenter/TemplateAutoIndentTest.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.indenter
2 |
3 | import org.eclipse.jface.text.IDocument
4 | import org.eclipse.jface.text.Document
5 | import org.eclipse.jface.text.DocumentCommand
6 | import org.junit.Assert._
7 | import org.scalaide.play2.templateeditor.TemplateAutoIndentStrategy
8 | import org.junit.ComparisonFailure
9 | import org.junit.Test
10 | import org.eclipse.jface.text.TextUtilities
11 |
12 | object TemplateAutoIndentTest {
13 | class TestCommand(cOffset: Int, cLength: Int, cText: String, cCaretOffset: Int, cShiftsCaret: Boolean, cDoIt: Boolean) extends DocumentCommand {
14 | caretOffset = cCaretOffset
15 | doit = cDoIt
16 | length = cLength
17 | offset = cOffset
18 | text = cText
19 | shiftsCaret = cShiftsCaret
20 | }
21 |
22 | }
23 |
24 | class TemplateAutoIndentTest {
25 | import TemplateAutoIndentTest._
26 |
27 | /** Tests if the input string is equal to the expected output, and the
28 | * output caret position is correct.
29 | *
30 | * The '^' character denotes the caret position, both for input and
31 | * expected output.
32 | */
33 | def test(input: String, expectedOutput: String) {
34 | require(input.count(_ == '^') == 1, "the cursor in the input isn't set correctly")
35 | require(expectedOutput.count(_ == '^') == 1, "the cursor in the expected output isn't set correctly")
36 |
37 | def createDocument(input: String): IDocument = {
38 | val rawInput = input.filterNot(_ == '^')
39 | new Document(rawInput)
40 | }
41 |
42 | val doc = createDocument(input)
43 |
44 | def createTestCommand(input: String): TestCommand = {
45 | val pos = input.indexOf('^')
46 | new TestCommand(pos, 0, TextUtilities.getDefaultLineDelimiter(doc), -1, false, true)
47 | }
48 |
49 | val cmd = createTestCommand(input)
50 | val strategy = new TemplateAutoIndentStrategy(2, useSpacesForTabs = true)
51 |
52 | strategy.customizeDocumentCommand(doc, cmd)
53 |
54 | val m = cmd.getClass.getSuperclass.getDeclaredMethod("execute", classOf[IDocument])
55 | m.setAccessible(true)
56 | m.invoke(cmd, doc)
57 |
58 | val expected = expectedOutput.replaceAll("\\^", "")
59 | val actual = doc.get()
60 |
61 | if (expected != actual) {
62 | throw new ComparisonFailure("", expected, actual)
63 | }
64 |
65 | assertEquals("Caret position is wrong", cmd.caretOffset, expectedOutput.indexOf('^'))
66 | }
67 |
68 | @Test
69 | def indentPrevLine() {
70 | test(
71 | """
72 | foo^""",
73 | """
74 | foo
75 | ^""")
76 | }
77 |
78 | @Test
79 | def indentAfterBrace() {
80 | test(
81 | """
82 | foo {^""",
83 | """
84 | foo {
85 | ^""")
86 | }
87 |
88 | @Test
89 | def indentAfterParen() {
90 | test(
91 | """
92 | foo (^""",
93 | """
94 | foo (
95 | ^""")
96 | }
97 |
98 | @Test
99 | def indentAfterBraceWithTail() {
100 | test(
101 | """
102 | foo { x => ^""",
103 | """
104 | foo { x =>
105 | ^""")
106 | }
107 |
108 | @Test
109 | def indentBetweenBraces() {
110 | test(
111 | """
112 | foo {^}""",
113 | """
114 | foo {
115 | ^
116 | }""")
117 | }
118 |
119 | @Test
120 | def indentBetweenBracesWithTail() {
121 | test(
122 | """
123 | foo { x => ^}""",
124 | """
125 | foo { x =>
126 | ^
127 | }""")
128 | }
129 |
130 | @Test
131 | def indentBalancedParens() {
132 | test(
133 | """
134 | foo { x => x + 1 }^
135 | """,
136 | """
137 | foo { x => x + 1 }
138 | ^
139 | """)
140 | }
141 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/src/org/scalaide/play2/lexical/PlayDocumentPartitionerTests.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.lexical
2 |
3 | import org.eclipse.jface.text.TypedRegion
4 | import org.junit.Assert.assertEquals
5 | import org.junit.Test
6 | import org.scalaide.play2.routeeditor.RouteTest
7 | import org.scalaide.play2.routeeditor.lexical.RoutePartitions
8 |
9 | class PlayDocumentPartitionerTests extends RouteTest {
10 |
11 | @Test
12 | def httpToken {
13 | testToken("G%ET / controller", new TypedRegion(0, 3, RoutePartitions.ROUTE_HTTP))
14 | }
15 |
16 | @Test
17 | def uriToken {
18 | testToken("GET /path/p%ath controller", new TypedRegion(4, 10, RoutePartitions.ROUTE_URI))
19 | }
20 |
21 | @Test
22 | def actionToken {
23 | testToken("GET / contro%ller", new TypedRegion(6, 10, RoutePartitions.ROUTE_ACTION))
24 | }
25 |
26 | @Test
27 | def beginningOfFileDefaultToken {
28 | testToken(" % GET / controller", new TypedRegion(0, 2, RoutePartitions.ROUTE_DEFAULT))
29 | }
30 |
31 | @Test
32 | def endOfFileDefaultToken {
33 | testToken("GET / controller %", new TypedRegion(17, 0, RoutePartitions.ROUTE_DEFAULT))
34 | }
35 |
36 | @Test
37 | def surroundedDefaultToken {
38 | testToken("GET % / controller", new TypedRegion(3, 3, RoutePartitions.ROUTE_DEFAULT))
39 | }
40 |
41 | private def testToken(rawContent: String, expectedToken: TypedRegion) = {
42 | val file = RouteFile(rawContent, List('%'))
43 | val caretOffset = file.caretOffset('%')
44 | val partition = file.document.getPartition(caretOffset)
45 | assertEquals("Unexpected token", expectedToken, partition)
46 | }
47 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/src/org/scalaide/play2/quickassist/ControllerMethodTest.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.quickassist
2 |
3 | import org.junit.Test
4 | import org.junit.Assert
5 |
6 | class ControllerMethodTest {
7 |
8 | @Test
9 | def emptyParamCallSyntax() {
10 | val meth = ControllerMethod("controllers.Application.index", List())
11 | Assert.assertEquals("Unexpected routeCallSyntax", "controllers.Application.index()", meth.toRouteCallSyntax)
12 | }
13 |
14 | @Test
15 | def stringParamCallSyntax() {
16 | val meth = ControllerMethod("controllers.Application.index", List(("param1", "String")))
17 | Assert.assertEquals("Unexpected routeCallSyntax", "controllers.Application.index(param1)", meth.toRouteCallSyntax)
18 |
19 | val meth1 = ControllerMethod("controllers.Application.index", List(("param1", "java.lang.String")))
20 | Assert.assertEquals("Unexpected routeCallSyntax", "controllers.Application.index(param1)", meth1.toRouteCallSyntax)
21 | }
22 |
23 | @Test
24 | def primitiveParamCallSyntax() {
25 | val meth = ControllerMethod("controllers.Application.index", List(("param1", "scala.Long")))
26 | Assert.assertEquals("Unexpected routeCallSyntax", "controllers.Application.index(param1: Long)", meth.toRouteCallSyntax)
27 |
28 | val meth1 = ControllerMethod("controllers.Application.index", List(("param1", "Long")))
29 | Assert.assertEquals("Unexpected routeCallSyntax", "controllers.Application.index(param1: Long)", meth1.toRouteCallSyntax)
30 | }
31 |
32 | @Test
33 | def primitiveParamCallJavaSyntax() {
34 | val meth = ControllerMethod("controllers.Application.index", List(("param1", "long")))
35 | Assert.assertEquals("Unexpected routeCallSyntax", "controllers.Application.index(param1: Long)", meth.toRouteCallSyntax)
36 |
37 | val meth1 = ControllerMethod("controllers.Application.index", List(("param1", "int")))
38 | Assert.assertEquals("Unexpected routeCallSyntax", "controllers.Application.index(param1: Int)", meth1.toRouteCallSyntax)
39 | }
40 |
41 | @Test
42 | def primitiveMultipleParamCallSyntax() {
43 | val meth = ControllerMethod("controllers.Application.index", List(("param1", "scala.Long"), ("param2", "Int"), ("param3", "String")))
44 | Assert.assertEquals("Unexpected routeCallSyntax", "controllers.Application.index(param1: Long, param2: Int, param3)", meth.toRouteCallSyntax)
45 | }
46 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/src/org/scalaide/play2/quickassist/ResolverTest.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.quickassist
2 |
3 | import org.junit.Test
4 | import org.junit.AfterClass
5 | import org.scalaide.core.testsetup.SDTTestUtils
6 | import org.scalaide.core.testsetup.TestProjectSetup
7 | import org.junit.Assert
8 |
9 | object ResolverTest extends TestProjectSetup("resolver", srcRoot = "/%s/app/", bundleName = "org.scala-ide.play2.tests") {
10 | @AfterClass
11 | def projectCleanUp() {
12 | SDTTestUtils.deleteProjects(project)
13 | }
14 | }
15 |
16 | class ResolverTest {
17 | import ResolverTest._
18 | import Assert._
19 |
20 | @Test
21 | def testScalaResolverPos() {
22 | val resolver = new ScalaControllerMethodResolver
23 |
24 | val scu = scalaCompilationUnit("controllers/Application.scala")
25 | val positions = SDTTestUtils.positionsOf(scu.getContents, "/*!*/")
26 |
27 | for (pos <- positions) {
28 | val cm = resolver.getControllerMethod(scu, pos)
29 | assertTrue(s"Could not resolve controller method at position $pos", cm.isDefined)
30 | assertTrue(s"${cm.get} is not in $scalaResolvedMethods", scalaResolvedMethods.contains(cm.get))
31 | }
32 | }
33 |
34 | @Test
35 | def testScalaResolverNeg() {
36 | val resolver = new ScalaControllerMethodResolver
37 |
38 | val scu = scalaCompilationUnit("controllers/NonController.scala")
39 | val positions = SDTTestUtils.positionsOf(scu.getContents, "/*!*/")
40 |
41 | for (pos <- positions) {
42 | val cm = resolver.getControllerMethod(scu, pos)
43 | assertTrue(s"Wrong controller method (${cm}) at position $pos", cm.isEmpty)
44 | }
45 | }
46 |
47 | @Test
48 | def testJavaResolverPos() {
49 | val resolver = new JavaControllerMethodResolver
50 | val cu = compilationUnit("controllers/JavaApplication.java")
51 | val positions = SDTTestUtils.positionsOf(cu.getBuffer().getCharacters(), "/*!*/")
52 |
53 | for (pos <- positions) {
54 | val cm = resolver.getControllerMethod(cu, pos)
55 | assertTrue(s"Could not resolve controller method at position $pos", cm.isDefined)
56 | assertTrue(s"${cm.get} is not in $javaResolvedMethods", javaResolvedMethods.contains(cm.get))
57 | }
58 | }
59 |
60 | @Test
61 | def testJavaResolverNeg() {
62 | val resolver = new ScalaControllerMethodResolver
63 |
64 | val scu = compilationUnit("controllers/JavaNonController.java")
65 | val positions = SDTTestUtils.positionsOf(scu.getBuffer().getCharacters(), "/*!*/")
66 |
67 | for (pos <- positions) {
68 | val cm = resolver.getControllerMethod(scu, pos)
69 | assertTrue(s"Wrong controller method (${cm}) at position $pos", cm.isEmpty)
70 | }
71 | }
72 |
73 | private val scalaResolvedMethods = Set(
74 | ControllerMethod("controllers.Application.index", List()),
75 | ControllerMethod("controllers.Application.post", List(("id", "Long"))),
76 | ControllerMethod("controllers.Application.postText", List(("text", "String"), ("id", "Int"))),
77 | ControllerMethod("controllers.Application.internalPostText1", List(("text", "String"), ("id", "Char"))),
78 | ControllerMethod("controllers.Application.internalPostText2", List(("text", "String"), ("id", "Short"))))
79 |
80 | private val javaResolvedMethods = Set(
81 | ControllerMethod("controllers.JavaApplication.index", List()),
82 | ControllerMethod("controllers.JavaApplication.index2", List(("lng", "long"))),
83 | ControllerMethod("controllers.JavaApplication.index3", List(("str", "java.lang.String"), ("id", "int"))),
84 | ControllerMethod("controllers.JavaApplication.index4", List(("f", "java.io.File"), ("id", "int"))))
85 | }
86 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/src/org/scalaide/play2/routeeditor/RouteActionTest.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.routeeditor
2 |
3 | import org.junit.Test
4 | import org.junit.Assert._
5 | import org.eclipse.jdt.internal.core.util.SimpleDocument
6 | import org.eclipse.jface.text.TypedRegion
7 | import org.scalaide.play2.routeeditor.lexical.RoutePartitions
8 | import org.eclipse.jface.text.ITypedRegion
9 | import org.eclipse.jface.text.IDocument
10 | import org.eclipse.jface.text.IRegion
11 | import org.eclipse.jface.text.Region
12 | import org.scalaide.play2.routeeditor.completion.CompletionComputerTest
13 |
14 | object RouteActionTest {
15 |
16 | def actionPartitionOffset(content: String): Int = {
17 | val regex = """\S*\s*/\S*\s*""".r
18 |
19 | regex.findFirstMatchIn(content) match {
20 | case Some(prefix) =>
21 | prefix.end
22 | case None =>
23 | fail("Unable to partition the test content")
24 | 0
25 | }
26 |
27 | }
28 |
29 | }
30 |
31 | class RouteActionTest extends CompletionComputerTest {
32 |
33 | override protected def createCompletionComputer = ???
34 |
35 | @Test
36 | def emptyParametersAction() {
37 |
38 | test("GET /path controller.Applic@ation.method()", "controller.Application", "method", Nil)
39 |
40 | }
41 |
42 | @Test
43 | def noParameterAction() {
44 |
45 | test("GET /path controller.Applica@tion.method", "controller.Application", "method", Nil)
46 |
47 | }
48 |
49 | @Test
50 | def actionInt() {
51 | test("GET /path controller.Applicat@ion.method(a: Int)", "controller.Application", "method", List(("a", "Int")))
52 | }
53 |
54 | @Test
55 | def actionString() {
56 | test("GET /path controller.Application.me@thod(b)", "controller.Application", "method", List(("b", "String")))
57 | }
58 |
59 | @Test
60 | def actionIntString() {
61 | test("GET /path controller.App@lication.method(c: Int, d)", "controller.Application", "method", List(("c", "Int"), ("d", "String")))
62 | }
63 |
64 | @Test
65 | def actionStringType() {
66 | test("GET /path controller.Application.method(e,@ f: some.Type)", "controller.Application", "method", List(("e", "String"), ("f", "some.Type")))
67 | }
68 |
69 | @Test
70 | def discardDefaultValue() {
71 | test("""GET /path controller.Application.me@thod(g ?= "gg", h: Int ?= 3)""", "controller.Application", "method", List(("g", "String"), ("h", "Int")))
72 | }
73 |
74 | private def test(
75 | documentContent: String,
76 | expectedTypeName: String,
77 | expectedMethodName: String,
78 | expectedParams: List[(String, String)]) {
79 |
80 | val file = new RouteCompletionFile(documentContent)
81 |
82 | val expected = new RouteAction(expectedTypeName, expectedMethodName, expectedParams, file.document.getPartition(file.caretOffset))
83 |
84 | val actual = RouteAction.routeActionAt(file.document, file.caretOffset)
85 |
86 | compare(expected, actual)
87 | }
88 |
89 | private def compare(expected: RouteAction, actual: Option[RouteAction]) {
90 | actual match {
91 | case Some(action) =>
92 | assertEquals("Wrong type", expected.typeName, action.typeName)
93 | assertEquals("Wrong method", expected.methodName, action.methodName)
94 | assertEquals("Wrong parameters", expected.params, action.params)
95 | assertEquals("Wrong region", expected.region, action.region)
96 | case None =>
97 | fail("A RouteAction is expected")
98 | }
99 | }
100 |
101 | }
102 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/src/org/scalaide/play2/routeeditor/RouteTest.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.routeeditor
2 |
3 | import org.scalaide.play2.routeeditor.lexical.RouteDocumentPartitioner
4 | import org.eclipse.jface.text.contentassist.ICompletionProposal
5 | import org.eclipse.jface.text.IDocument
6 | import org.junit.Assert._
7 | import org.eclipse.jface.text.Document
8 | import scala.annotation.tailrec
9 | import org.eclipse.jface.text.IRegion
10 | import org.eclipse.jface.text.Region
11 | import scala.collection.mutable.ListBuffer
12 | import scala.collection.mutable.StringBuilder
13 |
14 | trait RouteTest {
15 |
16 | protected class RouteFile(rawText: String, markers: List[Char] = List('@')) {
17 | private val text = rawText.stripMargin.trim
18 |
19 | private val (cleanedText: String, allMarkedPositions: Map[Char, List[Int]]) = extractPositions(rawText)
20 |
21 | val document: IDocument = {
22 | val doc = new Document(cleanedText)
23 | val partitioner = new RouteDocumentPartitioner
24 | partitioner.connect(doc)
25 | doc.setDocumentPartitioner(partitioner)
26 | doc
27 | }
28 |
29 | /** Return the only marked position by a marker char.
30 | */
31 | def caretOffset(marker: Char): Int = {
32 | val positions = allMarkedPositions(marker)
33 | assertEquals("too many marked positions", 1, positions.size)
34 | positions(0)
35 | }
36 |
37 | /** Return the region marked by one or two marker.
38 | */
39 | def selectedRegion(marker: Char = '@'): IRegion = {
40 | allMarkedPositions(marker) match {
41 | case a :: Nil =>
42 | new Region(a, 0)
43 | case a :: b :: Nil =>
44 | new Region(a, b - a)
45 | case _ =>
46 | fail("Should be 1 or 2 marked position, was: " + allMarkedPositions)
47 | null
48 | }
49 | }
50 |
51 | /** Return the regions marked by pairs of markers
52 | */
53 | def selectedRegions(marker: Char): Seq[IRegion] = {
54 | @tailrec
55 | def selectedRegions(positions: List[Int], acc: Vector[IRegion]): Vector[IRegion] = {
56 | positions match {
57 | case Nil =>
58 | acc
59 | case a :: b :: tail =>
60 | selectedRegions(tail, acc :+ new Region(a, b - a))
61 | case _ =>
62 | fail(s"Could not find matching pairs of $marker markers")
63 | null
64 | }
65 | }
66 |
67 | selectedRegions(allMarkedPositions(marker), Vector())
68 | }
69 |
70 | /** Remove the markers from the raw text, and return a Map with the positions of the
71 | * markers by type.
72 | */
73 | private def extractPositions(rawText: String): (String, Map[Char, List[Int]]) = {
74 | def addToMap(map: Map[Char, List[Int]], marker: Char, position: Int): Map[Char, List[Int]] = {
75 | val l = map(marker) :+ position
76 | map + ((marker, l))
77 | }
78 |
79 | @tailrec
80 | def extractPositions(chars: List[Char], currentIndex: Int, cleaned: StringBuilder, positions: Map[Char, List[Int]]): (String, Map[Char, List[Int]]) = {
81 | chars match {
82 | case Nil =>
83 | (cleaned.mkString, positions)
84 | case c :: tail if markers.contains(c)=>
85 | extractPositions(tail, currentIndex, cleaned, addToMap(positions, c, currentIndex))
86 | case c :: tail =>
87 | extractPositions(tail, currentIndex + 1, cleaned.append(c), positions)
88 | }
89 | }
90 |
91 | extractPositions(rawText.toList, 0, new StringBuilder(), markers.map(c => (c, Nil)).toMap)
92 | }
93 | }
94 |
95 | protected object RouteFile {
96 | def apply(text: String, markers: List[Char] = List('@')): RouteFile = new RouteFile(text, markers)
97 | }
98 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/src/org/scalaide/play2/routeeditor/RouteUriTest.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.routeeditor
2 |
3 | import org.junit.Test
4 | import org.junit.Assert._
5 |
6 | class RouteUriTest {
7 |
8 | @Test
9 | def parsingSimple {
10 | val route = RouteUri("/ab/cd/ef")
11 | assertEquals("Wrong uri parsing", List("ab", "cd", "ef"), route.parts)
12 | assertEquals("Wrong validity [should be true/valid]", true, route.isValid)
13 | }
14 |
15 | @Test
16 | def parsingInvalid {
17 | val route = RouteUri("ab/cd/ef")
18 | assertEquals("Wrong uri parsing", List("ab", "cd", "ef"), route.parts)
19 | assertEquals("Wrong validity [should be false/invalid]", false, route.isValid)
20 | }
21 |
22 | @Test
23 | def prefixLengthNoPrefix {
24 | testPrefixLength("/ab", List(), 1)
25 | }
26 |
27 | @Test
28 | def prefixLengthNoMatch {
29 | testPrefixLength("/ab", List("ba"), -1)
30 | }
31 |
32 | @Test
33 | def prefixLengthWholeMatch {
34 | testPrefixLength("/ab/cd", List("ab", "cd"), 6)
35 | }
36 |
37 | @Test
38 | def prefixLengthPrefixMatch {
39 | testPrefixLength("/ab/cd", List("ab"), 4)
40 | }
41 |
42 | @Test
43 | def prefixLengthInvalidUri {
44 | testPrefixLength("ab/cd", List("ab"), 3)
45 | }
46 |
47 | @Test
48 | def prefixLengthEmptyUri {
49 | testPrefixLength("/", List(), 1)
50 | }
51 |
52 | @Test
53 | def prefixLengthEmptyInvalidUri {
54 | testPrefixLength("", List(), 0)
55 | }
56 |
57 | private def testPrefixLength(rawUri: String, prefixParts: List[String], expectedLength: Int) {
58 | val route = RouteUri(rawUri)
59 | assertEquals("Wrong prefix length", expectedLength, route.prefixLength(prefixParts))
60 | }
61 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/src/org/scalaide/play2/routeeditor/completion/CompletionComputerTest.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.routeeditor.completion
2 |
3 | import org.eclipse.jface.text.Document
4 | import org.eclipse.jface.text.IDocument
5 | import org.eclipse.jface.text.ITextViewer
6 | import org.eclipse.jface.text.contentassist.ICompletionProposal
7 | import org.eclipse.jface.text.contentassist.IContentAssistProcessor
8 | import org.junit.Assert
9 | import org.mockito.Mockito.mock
10 | import org.mockito.Mockito.when
11 | import org.scalaide.play2.routeeditor.lexical.RouteDocumentPartitioner
12 | import org.eclipse.jface.text.IDocument
13 | import org.scalaide.play2.routeeditor.RouteTest
14 |
15 | trait CompletionComputerTest extends RouteTest {
16 |
17 | /** The expected completion proposal.*/
18 | trait ExpectedProposal
19 |
20 | /** Allows to convert the `ICompletionProposal` returned by the completion computer under test into
21 | * an `ExpectedProposal`, so that the returned completion can be compared against the test expectation.
22 | *
23 | * Subclasses will usually implement this as an '''implicit object''' so that it gets automatically
24 | * passed to `RouteFile.expectedCompletions`.
25 | */
26 | trait AsExpectedProposal[T <: ExpectedProposal] extends (ICompletionProposal => ExpectedProposal)
27 |
28 | protected def createCompletionComputer: IContentAssistProcessor
29 |
30 | protected val TestMarker: Char = '@'
31 |
32 | protected class RouteCompletionFile(rawText: String) extends RouteFile(rawText, List(TestMarker)) {
33 | private lazy val computeCompletionProposals: Array[ICompletionProposal] = {
34 | val contentAssist = createCompletionComputer
35 | val viewer = mock(classOf[ITextViewer])
36 | when(viewer.getDocument()).thenReturn(document)
37 | contentAssist.computeCompletionProposals(viewer, caretOffset)
38 | }
39 |
40 | def caretOffset: Int = caretOffset(TestMarker)
41 |
42 | def expectedCompletions[T <: ExpectedProposal](oracle: T*)(implicit converter: AsExpectedProposal[T]): Unit = {
43 | val completions = computeCompletionProposals.map(converter)
44 | Assert.assertEquals("Expected completions don't match.", oracle.toList, completions.toList)
45 | }
46 |
47 | }
48 | protected object RouteCompletionFile {
49 | def apply(text: String): RouteCompletionFile = new RouteCompletionFile(text.stripMargin)
50 | }
51 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/src/org/scalaide/play2/routeeditor/completion/HttpMethodCompletionComputerTest.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.routeeditor.completion
2 |
3 | import org.eclipse.jface.text.contentassist.ICompletionProposal
4 |
5 | import org.eclipse.jface.text.contentassist.IContentAssistProcessor
6 | import org.junit.Test
7 | import org.scalaide.play2.routeeditor.lexical.HTTPKeywords
8 |
9 | class HttpMethodCompletionComputerTest extends CompletionComputerTest {
10 |
11 | case class Proposal(httpMethod: String) extends ExpectedProposal
12 |
13 | implicit object Converter extends AsExpectedProposal[Proposal] {
14 | def apply(proposal: ICompletionProposal) = Proposal(proposal.getDisplayString)
15 | }
16 |
17 | override def createCompletionComputer: IContentAssistProcessor = new HttpMethodCompletionComputer
18 |
19 | private val AllHttpMethodsProposals = HTTPKeywords.Methods map Proposal
20 |
21 | @Test
22 | def HttpGET_completion() {
23 | val route = RouteCompletionFile { "G@" }
24 |
25 | route expectedCompletions Proposal("GET")
26 | }
27 |
28 | @Test
29 | def HttpGET_completion_is_case_insensitive() {
30 | val route = RouteCompletionFile { "g@" }
31 |
32 | route expectedCompletions Proposal("GET")
33 | }
34 |
35 | @Test
36 | def HTTP_PUT_POST_completion() {
37 | val route = RouteCompletionFile { "P@" }
38 |
39 | route expectedCompletions (Proposal("PATCH"), Proposal("POST"), Proposal("PUT"))
40 | }
41 |
42 | @Test
43 | def HTTP_HEAD_completion() {
44 | val route = RouteCompletionFile { "HeA@" }
45 |
46 | route expectedCompletions Proposal("HEAD")
47 | }
48 |
49 | @Test
50 | def HTTP_DELETE_completion() {
51 | val route = RouteCompletionFile { "de@" }
52 |
53 | route expectedCompletions Proposal("DELETE")
54 | }
55 |
56 | @Test
57 | def show_all_HTTP_methods_when_word_doesnt_match() {
58 | val route = RouteCompletionFile { "DET@" }
59 |
60 | route expectedCompletions (AllHttpMethodsProposals: _*)
61 | }
62 |
63 | @Test
64 | def all_Http_Method_completion_at_beginning_of_empty_line() {
65 | val route = RouteCompletionFile { "@" }
66 |
67 | route expectedCompletions (AllHttpMethodsProposals: _*)
68 | }
69 |
70 | @Test
71 | def all_Http_Method_completetion_at_beginning_of_empty_preceded_by_empty_line() {
72 | val route = RouteCompletionFile { "\n@" }
73 | route expectedCompletions (AllHttpMethodsProposals: _*)
74 | }
75 |
76 | @Test
77 | def all_Http_Method_completion_at_end_of_empty_line() {
78 | val route = RouteCompletionFile {
79 | // whitespaces before the '*' are relevant for this test!
80 | " @"
81 | }
82 |
83 | route expectedCompletions (AllHttpMethodsProposals: _*)
84 | }
85 |
86 | @Test
87 | def all_Http_Method_completion_in_middle_of_empty_line() {
88 | val route = RouteCompletionFile {
89 | // whitespaces after the '*' are relevant for this test!
90 | " @ "
91 | }
92 |
93 | route expectedCompletions (AllHttpMethodsProposals: _*)
94 | }
95 |
96 | @Test
97 | def all_Http_Method_completion_when_cursor_is_on_already_valid_Http_method() {
98 | val route = RouteCompletionFile { "G@ET" }
99 |
100 | route expectedCompletions (AllHttpMethodsProposals: _*)
101 | }
102 |
103 | @Test
104 | def GET_Http_Method_completion_returned() {
105 | val route = RouteCompletionFile {
106 | // whitespaces after the '*' is relevant for this test!
107 | "G@ "
108 | }
109 |
110 | route expectedCompletions Proposal("GET")
111 | }
112 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/src/org/scalaide/play2/routeeditor/hyperlink/MethodFinderTest.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.routeeditor.hyperlink
2 |
3 | import org.junit.Test
4 | import org.junit.Assert._
5 | import org.scalaide.core.testsetup.TestProjectSetup
6 | import org.eclipse.jdt.core.IJavaElement
7 | import org.eclipse.jdt.core.IMethod
8 | import org.eclipse.jdt.core.Signature
9 | import org.junit.Test
10 | import scala.Array.apply
11 | import scala.Array.canBuildFrom
12 | import org.junit.AfterClass
13 | import org.scalaide.core.testsetup.SDTTestUtils
14 |
15 | object MethodFinderTest extends TestProjectSetup("aProject", bundleName = "org.scala-ide.play2.tests") {
16 | @AfterClass
17 | def projectCleanUp() {
18 | SDTTestUtils.deleteProjects(project)
19 | }
20 | }
21 |
22 | class MethodFinderTest {
23 | MethodFinderTest
24 |
25 | val finder = new MethodFinder(MethodFinderTest.project.javaProject)
26 | import finder._
27 |
28 | @Test
29 | def getParametersStringTest() = {
30 | def t = testForGetParametersString _
31 | t ("(A)", Array("A"))
32 | t ("(A,B)", Array("A", "B"))
33 | t ("(A,B,C)", Array("A", "B", "C"))
34 | t ("()", Array())
35 | }
36 |
37 | private def testForGetParametersString(expected: String, parameterTypes: Array[String]) = {
38 | val actual = getParametersString(parameterTypes)
39 | assertEquals("getParametersString() is not correct", expected, actual)
40 | }
41 |
42 | @Test
43 | def methodSearchTest() = {
44 | def t = testForMethodSearch _
45 | t ("JavaClass.method1", Array())
46 | t ("JavaClass.method2", Array())
47 | t ("JavaClass.method2", Array("String"))
48 | t ("JavaClass.method2", Array("int"))
49 | t ("JavaClass.method2", Array("int", "String"))
50 | t ("JavaClass.method2", Array("Integer"))
51 | }
52 |
53 | private def testForMethodSearch(methodName: String, parameterTypes: Array[String]) = {
54 | val actual = dec(searchMethod(methodName, parameterTypes))
55 | // as IMethod.getParameterTypes returns signature of types, we have to get signature for types!
56 | val expected = methodName + getParametersString(parameterTypes map (Signature.createTypeSignature(_, false)))
57 | assertEquals("Could not find method", expected, actual)
58 | }
59 |
60 | private def dec(methods: Array[IJavaElement]): String = {
61 | if (methods.length != 1)
62 | return ""
63 | val method = methods(0).asInstanceOf[IMethod]
64 | val className = method.getParent.getElementName
65 | val methodName = method.getElementName
66 | val parameterTypes = method.getParameterTypes // It returns signature of parameter types!
67 | val paramsString = getParametersString(parameterTypes)
68 | className + "." + methodName + paramsString
69 | }
70 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/src/org/scalaide/play2/routeeditor/lexical/AbstractRouteScannerTest.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.routeeditor.lexical
2 |
3 | import org.eclipse.jface.text.rules.IToken
4 | import org.eclipse.jface.text.rules.Token
5 | import org.junit.Assert.assertEquals
6 | import org.scalaide.play2.PlayPlugin
7 |
8 | abstract class AbstractRouteScannerTest {
9 | protected val prefStore = PlayPlugin.preferenceStore
10 | protected val scanner : AbstractRouteScanner
11 | protected val defaultToken = scanner.getDefaultReturnToken
12 | protected val wsToken = Token.WHITESPACE
13 | protected val eofToken = Token.EOF
14 |
15 | protected def check(expected: IToken) = {
16 | assertEquals(expected, scanner.nextToken())
17 | }
18 |
19 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/src/org/scalaide/play2/routeeditor/lexical/RouteActionScannerTest.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.routeeditor.lexical
2 |
3 | import org.eclipse.jface.text.Document
4 | import org.eclipse.jface.text.rules.Token
5 | import org.junit.Test
6 |
7 | class RouteActionScannerTest extends AbstractRouteScannerTest {
8 | override val scanner = new RouteActionScanner(prefStore)
9 |
10 | val packageToken = scanner.asInstanceOf[RouteActionScanner].packageToken
11 | val classToken = scanner.asInstanceOf[RouteActionScanner].classToken
12 | val methodToken = scanner.asInstanceOf[RouteActionScanner].methodToken
13 |
14 | @Test
15 | def methodTest1() = {
16 | val content = "show()"
17 | val document = new Document(content)
18 | scanner.setRange(document, 0, content.length)
19 |
20 | check(methodToken)
21 | check(defaultToken)
22 | check(Token.EOF)
23 | }
24 | @Test
25 | def methodTest2() = {
26 | val content = "show(a: Int)"
27 | val document = new Document(content)
28 | scanner.setRange(document, 0, content.length)
29 |
30 | check(methodToken)
31 | check(defaultToken)
32 | check(Token.EOF)
33 | }
34 | @Test
35 | def methodTest3() = {
36 | val content = "show(a ?= \"\")"
37 | val document = new Document(content)
38 | scanner.setRange(document, 0, content.length)
39 |
40 | check(methodToken)
41 | check(defaultToken)
42 | check(Token.EOF)
43 | }
44 | @Test
45 | def classMethodTest1() = {
46 | val content = "A.show(a ?= \"\")"
47 | val document = new Document(content)
48 | scanner.setRange(document, 0, content.length)
49 |
50 | check(classToken)
51 | check(defaultToken)
52 | check(methodToken)
53 | check(defaultToken)
54 | check(Token.EOF)
55 | }
56 |
57 | @Test
58 | def classMethodTest2() = {
59 | val content = "A.B.C.D_1.show(a ?= \"\")"
60 | val document = new Document(content)
61 | scanner.setRange(document, 0, content.length)
62 |
63 | check(classToken)
64 | check(defaultToken)
65 | check(classToken)
66 | check(defaultToken)
67 | check(classToken)
68 | check(defaultToken)
69 | check(classToken)
70 | check(defaultToken)
71 | check(methodToken)
72 | check(defaultToken)
73 | check(Token.EOF)
74 | }
75 |
76 | @Test
77 | def packageClassMethodTest1() = {
78 | val content = "test.Class.show()"
79 | val document = new Document(content)
80 | scanner.setRange(document, 0, content.length)
81 |
82 | check(packageToken)
83 | check(classToken)
84 | check(defaultToken)
85 | check(methodToken)
86 | check(defaultToken)
87 | check(Token.EOF)
88 | }
89 | @Test
90 | def packageClassMethodTest2() = {
91 | val content = "test.test1.Class.show()"
92 | val document = new Document(content)
93 | scanner.setRange(document, 0, content.length)
94 |
95 | check(packageToken)
96 | check(classToken)
97 | check(defaultToken)
98 | check(methodToken)
99 | check(defaultToken)
100 | check(Token.EOF)
101 | }
102 | @Test
103 | def packageClassMethodTest3() = {
104 | val content = "test.test1.t_2.t__3.tAt.Class.show()"
105 | val document = new Document(content)
106 | scanner.setRange(document, 0, content.length)
107 |
108 | check(packageToken)
109 | check(classToken)
110 | check(defaultToken)
111 | check(methodToken)
112 | check(defaultToken)
113 | check(Token.EOF)
114 | }
115 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/src/org/scalaide/play2/routeeditor/lexical/RouteURIScannerTest.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.routeeditor.lexical
2 |
3 | import org.eclipse.jface.text.Document
4 | import org.junit.Test
5 |
6 | class RouteURIScannerTest extends AbstractRouteScannerTest {
7 | override val scanner = new RouteURIScanner(prefStore)
8 |
9 | private val dynamicToken = scanner.asInstanceOf[RouteURIScanner].dynamic
10 |
11 | @Test
12 | def dynamicTest1() = {
13 | val content = "/hello/route/*id"
14 | val document = new Document(content)
15 | scanner.setRange(document, 0, content.length)
16 |
17 | check(defaultToken)
18 | check(dynamicToken)
19 | check(eofToken)
20 | }
21 |
22 | @Test
23 | def dynamicTest2() = {
24 | val content = "/hello/:id"
25 | val document = new Document(content)
26 | scanner.setRange(document, 0, content.length)
27 |
28 | check(defaultToken)
29 | check(dynamicToken)
30 | check(eofToken)
31 | }
32 |
33 | @Test
34 | def dynamicTest3() = {
35 | val content = "/hello/route_1/$id_2"
36 | val document = new Document(content)
37 | scanner.setRange(document, 0, content.length)
38 |
39 | check(defaultToken)
40 | check(dynamicToken)
41 | check(eofToken)
42 | }
43 |
44 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/src/org/scalaide/play2/templateeditor/BeforeAfterTemplateVersion.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.templateeditor
2 |
3 | import org.junit.After
4 | import org.junit.Before
5 | import org.scalaide.play2.templateeditor.processing.TemplateVersionExhibitor
6 |
7 | trait BeforeAfterTemplateVersion {
8 | @Before def setUp(): Unit = {
9 | TemplateVersionExhibitor.set(Some("2.6"))
10 | }
11 |
12 | @After def tearDown(): Unit = {
13 | TemplateVersionExhibitor.clean()
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/src/org/scalaide/play2/templateeditor/lexical/TemplatePartitionTokniserTest.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.templateeditor.lexical
2 |
3 | import scala.annotation.tailrec
4 |
5 | import org.eclipse.jdt.internal.core.util.SimpleDocument
6 | import org.eclipse.jface.text.TypedRegion
7 | import org.junit.Assert.assertEquals
8 | import org.junit.Assert.assertTrue
9 | import org.junit.Test
10 | import org.scalaide.play2.templateeditor.BeforeAfterTemplateVersion
11 | import org.scalaide.util.eclipse.RegionUtils
12 |
13 | class TemplatePartitionTokeniserTest extends BeforeAfterTemplateVersion {
14 |
15 | def s(offset: Int, length: Int) = new TypedRegion(offset, length, TemplatePartitions.TEMPLATE_SCALA)
16 | def d(offset: Int, length: Int) = new TypedRegion(offset, length, TemplatePartitions.TEMPLATE_DEFAULT)
17 | def c(offset: Int, length: Int) = new TypedRegion(offset, length, TemplatePartitions.TEMPLATE_COMMENT)
18 | def tg(offset: Int, length: Int) = new TypedRegion(offset, length, TemplatePartitions.TEMPLATE_TAG)
19 | def p(offset: Int, length: Int) = new TypedRegion(offset, length, TemplatePartitions.TEMPLATE_PLAIN)
20 |
21 | @Test
22 | def definitionSection() {
23 | val p1 = "@(param: String)"
24 | testForTokenise(List(d(0, 1), s(1, p1.length() - 1)), p1)
25 | }
26 |
27 | @Test
28 | def simpleTokeniseTest() = {
29 | def t = testForTokenise _
30 | val p2 = "@*comment*@"
31 | t(List(c(0, p2.length())), p2)
32 | val p3 = ""
33 | t(List(tg(0, 10), tg(10, 11)), p3)
34 | val p4 = "Some plain text"
35 | t(List(p(0, p4.length())), p4)
36 | val p5 = "@methodCall(arg)"
37 | t(List(d(0, 1), s(1, p5.length() - 1)), p5)
38 | val p6 = """@{val blockOfScalaCode = ""}"""
39 | t(List(d(0, 1), s(1, p6.length() - 1)), p6)
40 | }
41 |
42 |
43 |
44 | @Test
45 | def complexTokeniseTest() = {
46 | def t = testForTokenise _
47 | // bug #20
48 | // reusable block
49 | val p1 = """@test = {
50 | is viewed
51 | }"""
52 | t(List(d(0, 1), s(1, 4), d(5, 4), p(9, 3), p(12, 10), d(22, 1)), p1)
53 | // bug #20
54 | // reusable block with scala code
55 | val p2 = """@test = @{
56 | val x = "x string"
57 | }"""
58 | t(List(d(0, 1), s(1, 4), d(5, 4), s(9, 22)), p2)
59 | // bug #18
60 | // for statements without yield
61 | val p3 = """@for()"""
62 | t(List(d(0, 1), s(1, 5)), p3)
63 | }
64 |
65 | private def testForTokenise(expected: List[TypedRegion], program: String) = {
66 | val tokeniser = new TemplatePartitionTokeniser
67 | val actual = tokeniser.tokenise(new SimpleDocument(program))
68 |
69 | @tailrec
70 | def noOverlap(list: List[TypedRegion]): Boolean = {
71 | list match {
72 | case head :: second :: tail =>
73 | import org.scalaide.util.eclipse.RegionUtils.RichRegion
74 | !head.intersects(second) && noOverlap(list.tail)
75 | case _ =>
76 | true
77 | }
78 | }
79 |
80 | def complete: Boolean = {
81 | def testComplete(start: Int, list: List[TypedRegion]): Boolean = {
82 | list match {
83 | case hd :: tail => if (start == hd.getOffset()) testComplete(hd.getOffset() + hd.getLength(), tail) else false
84 | case _ => start == program.length()
85 | }
86 | }
87 | testComplete(0, actual)
88 | }
89 |
90 | assertTrue("list has overlap", noOverlap(actual))
91 | assertTrue("list is not complete", complete)
92 | assertEquals("list doesn't match", expected, actual)
93 | }
94 |
95 | }
96 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/src/org/scalaide/play2/templateeditor/sse/TemplateContentDescriberTest.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.templateeditor.sse
2 |
3 | import org.junit.Test
4 | import org.junit.Assert._
5 | import org.eclipse.core.runtime.content.IContentDescriber
6 | import java.io.ByteArrayInputStream
7 |
8 | class TemplateContentDescriberTest {
9 |
10 | import IContentDescriber._
11 |
12 | @Test
13 | def emptyFile() {
14 | test("Empty file", "", INDETERMINATE)
15 | }
16 |
17 | @Test
18 | def notTemplate() {
19 | test("Not template", "", INVALID)
20 | }
21 |
22 | @Test
23 | def notTemplateWithEmptyLines() {
24 | test("Not template with emtyp lines", """
25 |
26 |
27 |
28 | """, INVALID)
29 | }
30 |
31 | @Test
32 | def notTemplateWithLeadingSpaces() {
33 | test("Not template with leading spaces", " ", INVALID)
34 | }
35 |
36 | @Test
37 | def startWithComment() {
38 | test("Start with comment", "@********@", VALID)
39 | }
40 |
41 | @Test
42 | def startWithParameters() {
43 | test("Start with parameters", "@(abc: Int)(test: String)", VALID)
44 | }
45 |
46 | @Test
47 | def startWithCommentWithEmptyLines() {
48 | test("Start with comment with emtyp lines", """
49 |
50 |
51 | @********@
52 | """, VALID)
53 | }
54 |
55 | @Test
56 | def startWithParametersWithEmptyLines() {
57 | test("Start with parameters with emtyp lines", """
58 |
59 |
60 | @(abc: Int)(test: String)
61 | """, VALID)
62 | }
63 |
64 | @Test
65 | def startWithCommentWithLeadingSpaces() {
66 | test("Start with comment with leading spaces", " @********@", VALID)
67 | }
68 |
69 | @Test
70 | def startWithParametersWithLeadingSpaces() {
71 | test("Start with parameters with leading spaces", " @(abc: Int)(test: String)", VALID)
72 | }
73 |
74 | private def test(description: String, content: String, expectedValue: Int) {
75 | val describer = new TemplateContentDescriber()
76 |
77 | assertEquals("Wrong value for " + description, expectedValue, describer.describe(new ByteArrayInputStream(content.getBytes("UTF-8")), null))
78 | }
79 |
80 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/test-workspace/.gitignore:
--------------------------------------------------------------------------------
1 | bin/
2 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/test-workspace/aProject/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/test-workspace/aProject/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | aProject
4 |
5 |
6 |
7 |
8 |
9 | org.scala-ide.sdt.core.scalabuilder
10 |
11 |
12 |
13 |
14 |
15 | org.scala-ide.sdt.core.scalanature
16 | org.eclipse.jdt.core.javanature
17 |
18 |
19 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/test-workspace/aProject/app/views/index.scala.html:
--------------------------------------------------------------------------------
1 | @(message: String)
2 |
3 | @message
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/test-workspace/aProject/app/views/scala_compiler_error.scala.html:
--------------------------------------------------------------------------------
1 | @(message: String)
2 |
3 | @main("Welcome") {
4 | @foo
5 | }
6 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/test-workspace/aProject/app/views/template_parse_error.scala.html:
--------------------------------------------------------------------------------
1 | @(message: String)
2 |
3 | @main("Welcome") {
4 | @
5 | }
6 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/test-workspace/aProject/app/views/template_unclosed_comment.scala.html:
--------------------------------------------------------------------------------
1 | @*
2 |
3 | @(message: String)
4 |
5 | @main("Welcome") {
6 | @
7 | }
8 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/test-workspace/aProject/moreviews/more.scala.html:
--------------------------------------------------------------------------------
1 | @(message: String)
2 |
3 | @message
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/test-workspace/aProject/route:
--------------------------------------------------------------------------------
1 | GET /clients/:id controllers.Clients.show(id: Long)
2 | # Display a client.
3 | GET /clients/:id controllers.Clients.show(id: Long)
4 | GET /clients controllers.Clients.list()
5 | GET /clients/:id controllers.Clients.show(id: Long)
6 | GET /files/*name controllers.Application.download(name)
7 | GET /clients/$id<[0-9]+> controllers.Clients.show(id: Long)
8 | GET / controllers.Application.homePage()
9 | # Extract the page parameter from the path.
10 | # i.e. http://myserver.com/index
11 | GET /:page controllers.Application.show(page)
12 | # Extract the page parameter from the query string.
13 | # i.e. http://myserver.com/?page=index
14 | GET / controllers.Application.show(page)
15 | GET /client/:id controllers.Clients.show(id: Long)
16 | # Extract the page parameter from the path, or fix the value for /
17 | GET / controllers.Application.show(page = "home")
18 | GET /:page controllers.Application.show(page)
19 | # Pagination links, like /clients?page=3
20 | GET /clients controllers.Clients.list(page: Integer ?= 1)
21 | # Hello action
22 | GET /hello/:name controllers.Application.hello(name)
23 |
24 | # Amir's tests
25 | GET /hello/:str controllers.Test.test_underline() #comment at here!
26 | test.test.test2.A.show()
27 | Integer.parseInt(a: String)
28 | #kdjfa /dkfjsa
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/test-workspace/aProject/src/org/example/JavaClass.java:
--------------------------------------------------------------------------------
1 |
2 | public class JavaClass {
3 | public void method1(){
4 |
5 | }
6 |
7 | public void method2(){
8 |
9 | }
10 |
11 | public void method2(int a){
12 |
13 | }
14 |
15 | public void method2(String s){
16 |
17 | }
18 |
19 | public void method2(Integer i){
20 |
21 | }
22 |
23 | public void method2(int a, String s){
24 |
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/test-workspace/aProject/src/org/example/ScalaClass.scala:
--------------------------------------------------------------------------------
1 | package org.example
2 |
3 | class ScalaClass {
4 |
5 | }
6 |
7 | object ScalaClass {
8 |
9 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/test-workspace/resolver/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/test-workspace/resolver/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | resolver
4 |
5 |
6 |
7 |
8 |
9 | org.scala-ide.sdt.core.scalabuilder
10 |
11 |
12 |
13 |
14 |
15 | org.scala-ide.sdt.core.scalanature
16 | org.eclipse.jdt.core.javanature
17 |
18 |
19 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/test-workspace/resolver/app/controllers/Application.scala:
--------------------------------------------------------------------------------
1 | package controllers
2 |
3 | import play.api.mvc.{Controller, Action}
4 |
5 | object Application {
6 |
7 | def/*!*/ index = Action {
8 | }
9 |
10 | def/*!*/ post(id: Long) = Action {
11 | }
12 |
13 | def/*!*/ postText(text: String, id: Int) = Action {
14 | }
15 |
16 | def internalPostText1(text: String, /*!*/id: Char) = Action {
17 | }
18 |
19 | def internalPostText2(text: String, id: Short) = Action {
20 | /*!*/
21 | }
22 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/test-workspace/resolver/app/controllers/JavaApplication.java:
--------------------------------------------------------------------------------
1 | package controllers;
2 |
3 | import play.mvc.Controller;
4 | import play.mvc.Result;
5 | import java.io.File;
6 |
7 | public class JavaApplication extends Controller {
8 |
9 | public static Result index() {
10 | /*!*/
11 | return null;
12 | }
13 |
14 | public static Result index2(long lng) {
15 | /*!*/
16 | return null;
17 | }
18 |
19 | public static Result index3(String str, int id) {
20 | /*!*/
21 | return null;
22 | }
23 |
24 | public static Result index4(File f, int id) {
25 | /*!*/
26 | return null;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/test-workspace/resolver/app/controllers/JavaNonController.java:
--------------------------------------------------------------------------------
1 | package controllers;
2 |
3 | import play.mvc.Controller;
4 | import play.mvc.Result;
5 |
6 | public class JavaNonController extends Controller {
7 |
8 | // not static
9 | public Result index() {
10 | /*!*/
11 | return null;
12 | }
13 |
14 | // not returning resultResult
15 | public static String index2(long lng) {
16 | /*!*/
17 | return null;
18 | }
19 |
20 | // not public
21 | static Result index3(String str, int id) {
22 | /*!*/
23 | return null;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/test-workspace/resolver/app/controllers/NonController.scala:
--------------------------------------------------------------------------------
1 | package controllers
2 |
3 | import play.api.mvc.{Controller, Action}
4 |
5 | trait Action
6 |
7 | object NonController {
8 |
9 | def/*!*/ index = new Action
10 |
11 | def/*!*/ post(id: Long) = "dummy"
12 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/test-workspace/resolver/src/play/api/mvc/Action.scala:
--------------------------------------------------------------------------------
1 | package play.api.mvc
2 |
3 | class Action extends EssentialAction
4 |
5 | object Action {
6 | def apply[A](f: => A) = new Action
7 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/test-workspace/resolver/src/play/api/mvc/EssentialAction.scala:
--------------------------------------------------------------------------------
1 | package play.api.mvc
2 |
3 | class EssentialAction
4 |
5 | object EssentialAction {
6 | def apply[A](f: => A) = new EssentialAction
7 | }
8 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/test-workspace/resolver/src/play/mvc/Controller.java:
--------------------------------------------------------------------------------
1 | package play.mvc;
2 |
3 | public abstract class Controller {}
4 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/test-workspace/resolver/src/play/mvc/Result.java:
--------------------------------------------------------------------------------
1 | package play.mvc;
2 |
3 | abstract class Result {}
4 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/test-workspace/routeActionCompletions/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/test-workspace/routeActionCompletions/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | routeActionCompletions
4 |
5 |
6 |
7 |
8 |
9 | org.scala-ide.sdt.core.scalabuilder
10 |
11 |
12 |
13 |
14 |
15 | org.scala-ide.sdt.core.scalanature
16 | org.eclipse.jdt.core.javanature
17 |
18 |
19 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/test-workspace/routeActionCompletions/app/RootScalaApplication.scala:
--------------------------------------------------------------------------------
1 | import play.mvc._
2 |
3 | class RootScalaApplication {
4 | def simple: AnyRef = ???
5 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/test-workspace/routeActionCompletions/app/RootStaticJavaApplication.java:
--------------------------------------------------------------------------------
1 | import play.*;
2 | import play.mvc.*;
3 |
4 | public class RootStaticJavaApplication extends Controller {
5 | public static Result simple() {
6 | return new Result() {};
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/test-workspace/routeActionCompletions/app/ScalaPackage/package.scala:
--------------------------------------------------------------------------------
1 | package object ScalaPackage {
2 | def simple: AnyRef = ???
3 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/test-workspace/routeActionCompletions/app/controllers/java/AbstractApplication.java:
--------------------------------------------------------------------------------
1 | package controllers.java;
2 |
3 | import play.*;
4 | import play.mvc.*;
5 |
6 | public abstract class AbstractApplication extends Controller {
7 | public static Result hello(String name) {
8 | return new Result {};
9 | }
10 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/test-workspace/routeActionCompletions/app/controllers/java/Application.java:
--------------------------------------------------------------------------------
1 | package controllers.java;
2 |
3 | import play.*;
4 | import play.mvc.*;
5 |
6 | public class Application extends Controller {
7 |
8 | public static Result hello(String name) {
9 | return new Result {};
10 | }
11 |
12 | public static Result withIntegerArg(Integer i) {
13 | return new Result {};
14 | }
15 |
16 | public static void nonActionMethod(String name) {}
17 |
18 | public Result nonStaticMethod(String name) {
19 | return new Result {};
20 | }
21 |
22 | public static Result fieldIsNotValidAction = new Result {};
23 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/test-workspace/routeActionCompletions/app/controllers/java/InterfaceApplication.java:
--------------------------------------------------------------------------------
1 | package controllers.java;
2 |
3 |
4 | public interface InterfaceApplication {
5 |
6 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/test-workspace/routeActionCompletions/app/controllers/java/SubApplication.java:
--------------------------------------------------------------------------------
1 | package controllers.java;
2 |
3 | import play.*;
4 | import play.mvc.*;
5 |
6 | public class SubApplication extends Application {
7 |
8 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/test-workspace/routeActionCompletions/app/controllers/scala/AbstractApp.scala:
--------------------------------------------------------------------------------
1 | package controllers.scala
2 |
3 | import play.api._
4 | import play.api.mvc._
5 |
6 | abstract class AbstractApp {
7 | def actionMethod() = Action {}
8 |
9 | val actionVal = Action {}
10 |
11 | def nonActionMethod(): Unit = ()
12 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/test-workspace/routeActionCompletions/app/controllers/scala/ActionWithMangledName.scala:
--------------------------------------------------------------------------------
1 | package controllers.scala
2 |
3 | import play.api._
4 | import play.api.mvc._
5 |
6 | object ActionWithMangledName {
7 | def ++==++() = Action {}
8 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/test-workspace/routeActionCompletions/app/controllers/scala/AppClass.scala:
--------------------------------------------------------------------------------
1 | package controllers.scala
2 |
3 | import play.api._
4 | import play.api.mvc._
5 |
6 | class AppClass {
7 | def actionMethod() = Action {}
8 |
9 | val actionVal = Action {}
10 |
11 | def nonActionMethod(): Unit = ()
12 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/test-workspace/routeActionCompletions/app/controllers/scala/AppNotExtendingController.scala:
--------------------------------------------------------------------------------
1 | package controllers.scala
2 |
3 | import play.api._
4 | import play.api.mvc._
5 |
6 | object AppNotExtendingController {
7 | def actionMethod() = Action {}
8 |
9 | def nonActionMethod(): Unit = ()
10 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/test-workspace/routeActionCompletions/app/controllers/scala/MembersVisibility.scala:
--------------------------------------------------------------------------------
1 | package controllers.scala
2 |
3 | import play.api._
4 | import play.api.mvc._
5 |
6 | object MembersVisibility {
7 | private def actionMethod1() = Action {}
8 | private[scala] def actionMethod2() = Action {}
9 | protected def actionMethod3() = Action {}
10 | protected[scala] def actionMethod4() = Action {}
11 |
12 | private val actionVal1 = Action {}
13 | private[scala] val actionVal2 = Action {}
14 | protected val actionVal3 = Action {}
15 | protected[scala] val actionVal4 = Action {}
16 |
17 | def visibleMethod = Action {}
18 |
19 | /** The completion engine in the route file should NOT report abstract methods.*/
20 | def abstractMethod: Action
21 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/test-workspace/routeActionCompletions/app/controllers/scala/SubAppClass.scala:
--------------------------------------------------------------------------------
1 | package controllers.scala
2 |
3 | import play.api._
4 | import play.api.mvc._
5 |
6 | object SubAppClass extends AppClass
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/test-workspace/routeActionCompletions/app/controllers/scala/TraitApp.scala:
--------------------------------------------------------------------------------
1 | package controllers.scala
2 |
3 | import play.api._
4 | import play.api.mvc._
5 |
6 | trait TraitApp {
7 | def actionMethod() = Action {}
8 |
9 | def nonActionMethod(): Unit = ()
10 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/test-workspace/routeActionCompletions/app/controllers/scala/empty/Empty:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scala-ide/scala-ide-play2/d9c116f2c5e1e83b1093628395bc11e8dab377ac/org.scala-ide.play2.tests/test-workspace/routeActionCompletions/app/controllers/scala/empty/Empty
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/test-workspace/routeActionCompletions/app/controllers/simple/SimpleScalaPlayApp.scala:
--------------------------------------------------------------------------------
1 | package controllers.simple
2 |
3 | import play.api._
4 | import play.api.mvc._
5 |
6 | object SimpleScalaPlayApp extends Controller {
7 | def foo = Action {}
8 |
9 | def bar() = Action {}
10 |
11 | val buz = Action {}
12 |
13 | lazy val lazyBuz = Action {}
14 |
15 | var boo = Action {}
16 |
17 | def nonActionMethod: Unit = ()
18 |
19 | def withStringArg(s: String) = Action {}
20 |
21 | def withIntArg(i: Int) = Action {}
22 |
23 | def overloadedAction(s: String) = Action {}
24 | def overloadedAction(id: Long) = Action {}
25 | def overloadedAction() = Action {}
26 |
27 | def overloadedEssentialAction(s: String) = EssentialAction {}
28 | def overloadedEssentialAction(id: Long) = EssentialAction {}
29 | def overloadedEssentialAction() = EssentialAction {}
30 | }
31 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/test-workspace/routeActionCompletions/src/play/api/mvc/Action.scala:
--------------------------------------------------------------------------------
1 | package play.api.mvc
2 |
3 | trait Action extends EssentialAction
4 |
5 | object Action {
6 | def apply[A](f: => A) = new Action {}
7 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/test-workspace/routeActionCompletions/src/play/api/mvc/EssentialAction.scala:
--------------------------------------------------------------------------------
1 | package play.api.mvc
2 |
3 | trait EssentialAction
4 |
5 | object EssentialAction {
6 | def apply[A](f: => A) = new EssentialAction {}
7 | }
8 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/test-workspace/routeActionCompletions/src/play/mvc/Controller.java:
--------------------------------------------------------------------------------
1 | package play.mvc;
2 |
3 | public abstract class Controller {}
4 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/test-workspace/routeActionCompletions/src/play/mvc/Result.java:
--------------------------------------------------------------------------------
1 | package play.mvc;
2 |
3 | abstract public class Result {}
4 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/test-workspace/routeHyperlink/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/test-workspace/routeHyperlink/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | routeHyperlink
4 |
5 |
6 |
7 |
8 |
9 | org.scala-ide.sdt.core.scalabuilder
10 |
11 |
12 |
13 |
14 |
15 | org.scala-ide.sdt.core.scalanature
16 | org.eclipse.jdt.core.javanature
17 |
18 |
19 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/test-workspace/routeHyperlink/app/controllers/JavaApplication.java:
--------------------------------------------------------------------------------
1 | package controllers;
2 |
3 | import model.Element;
4 |
5 | public class JavaApplication {
6 |
7 | public static Object intro() {
8 | throw new UnsupportedOperationException();
9 | }
10 |
11 | public static Object withEmptyParams() {
12 | throw new UnsupportedOperationException();
13 | }
14 |
15 | public static Object pInt(int a) {
16 | throw new UnsupportedOperationException();
17 | }
18 |
19 | public static Object pString(String a) {
20 | throw new UnsupportedOperationException();
21 | }
22 |
23 | public static Object pRef(Element a) {
24 | throw new UnsupportedOperationException();
25 | }
26 |
27 | public static Object overloaded(int b) {
28 | throw new UnsupportedOperationException();
29 | }
30 |
31 | public static Object overloaded(String c) {
32 | throw new UnsupportedOperationException();
33 | }
34 |
35 | public static Object overloaded(Element b) {
36 | throw new UnsupportedOperationException();
37 | }
38 |
39 | public static Object overloaded(String s, Element b) {
40 | throw new UnsupportedOperationException();
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/test-workspace/routeHyperlink/app/controllers/ScalaApplication.scala:
--------------------------------------------------------------------------------
1 | package controllers
2 |
3 | import model.Element
4 |
5 | object ScalaApplication {
6 |
7 | def intro: AnyRef = ???
8 |
9 | def withEmptyParams(): AnyRef = ???
10 |
11 | def pInt(a: Int): AnyRef = ???
12 |
13 | def pString(a: String): AnyRef = ???
14 |
15 | def pRef(a: Element): AnyRef = ???
16 |
17 | def overloaded(b: Int): AnyRef = ???
18 |
19 | def overloaded(c: String): AnyRef = ???
20 |
21 | def overloaded(b: Element): AnyRef = ???
22 |
23 | def overloaded(s: String, b: Element): AnyRef = ???
24 | }
25 |
26 | class ScalaClass {
27 |
28 | def intro: AnyRef = ???
29 |
30 | def withEmptyParams(): AnyRef = ???
31 |
32 | def pInt(a: Int): AnyRef = ???
33 |
34 | def pString(a: String): AnyRef = ???
35 |
36 | def pRef(a: Element): AnyRef = ???
37 |
38 | def overloaded(b: Int): AnyRef = ???
39 |
40 | def overloaded(c: String): AnyRef = ???
41 |
42 | def overloaded(b: Element): AnyRef = ???
43 |
44 | def overloaded(s: String, b: Element): AnyRef = ???
45 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2.tests/test-workspace/routeHyperlink/app/model/Element.scala:
--------------------------------------------------------------------------------
1 | package model
2 |
3 | case class Element(id: Int)
--------------------------------------------------------------------------------
/org.scala-ide.play2.update-site/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | org.scala-ide.play2.update-site
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.pde.UpdateSiteBuilder
10 |
11 |
12 |
13 |
14 |
15 | org.eclipse.pde.UpdateSiteNature
16 |
17 |
18 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.update-site/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.scala-ide
7 | org.scala-ide.play2.build
8 | 0.11.0-SNAPSHOT
9 |
10 | org.scala-ide.play2.update-site
11 | eclipse-update-site
12 |
13 |
--------------------------------------------------------------------------------
/org.scala-ide.play2.update-site/site.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | -->
11 |
12 |
--------------------------------------------------------------------------------
/org.scala-ide.play2/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/org.scala-ide.play2/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | org.scala-ide.play2
4 |
5 |
6 |
7 |
8 |
9 | org.scala-ide.sdt.core.scalabuilder
10 |
11 |
12 |
13 | org.eclipse.pde.ManifestBuilder
14 |
15 |
16 |
17 | org.eclipse.pde.SchemaBuilder
18 |
19 |
20 |
21 |
22 | org.eclipse.pde.PluginNature
23 | org.scala-ide.sdt.core.scalanature
24 | org.eclipse.jdt.core.javanature
25 |
26 |
27 |
--------------------------------------------------------------------------------
/org.scala-ide.play2/META-INF/MANIFEST.MF:
--------------------------------------------------------------------------------
1 | Manifest-Version: 1.0
2 | Bundle-ManifestVersion: 2
3 | Bundle-Name: Play 2 Support for Scala IDE
4 | Bundle-SymbolicName: org.scala-ide.play2;singleton:=true
5 | Bundle-Version: 0.11.0.qualifier
6 | Bundle-Vendor: scala-ide.org
7 | Bundle-ActivationPolicy: lazy
8 | Bundle-Localization: plugin
9 | Require-Bundle:
10 | org.eclipse.core.runtime,
11 | org.eclipse.debug.ui,
12 | org.eclipse.help,
13 | org.eclipse.jdt.core,
14 | org.eclipse.jdt.debug.ui,
15 | org.eclipse.jdt.junit,
16 | org.eclipse.jdt.launching,
17 | org.eclipse.jdt.ui,
18 | org.eclipse.jface.text,
19 | org.eclipse.ui,
20 | org.eclipse.ui.console,
21 | org.eclipse.ui.editors,
22 | org.eclipse.ui.forms,
23 | org.eclipse.ui.ide,
24 | org.scala-lang.scala-library;bundle-version="[2.12,2.13)",
25 | org.scala-lang.scala-compiler;bundle-version="[2.12,2.13)",
26 | org.scala-lang.scala-reflect;bundle-version="[2.12,2.13)",
27 | org.scala-ide.sdt.core;bundle-version="[4.0.0,5.0.0)",
28 | org.eclipse.core.resources,
29 | scalariform,
30 | org.eclipse.core.filesystem,
31 | org.eclipse.wst.sse.ui,
32 | org.eclipse.wst.sse.core,
33 | org.eclipse.wst.html.ui,
34 | org.eclipse.wst.html.core,
35 | org.eclipse.wst.xml.core,
36 | org.eclipse.emf.common,
37 | org.eclipse.wst.xml.ui,
38 | org.eclipse.wst.css.core,
39 | org.eclipse.wst.validation,
40 | org.eclipse.wst.jsdt.web.ui,
41 | org.eclipse.wst.jsdt.web.core,
42 | org.eclipse.wst.jsdt.core,
43 | org.scala-lang.modules.scala-xml,
44 | org.scala-lang.modules.scala-parser-combinators
45 | Import-Package:
46 | com.ibm.icu.text;apply-aspects:=false;org.eclipse.swt.graphics;apply-aspects:=false,
47 | scala.tools.eclipse.contribution.weaving.jdt.ui.javaeditor.formatter;apply-aspects:=false,
48 | scala.xml,
49 | scala.util.parsing.input
50 | Bundle-RequiredExecutionEnvironment: JavaSE-1.6
51 | Bundle-Activator: org.scalaide.play2.PlayPlugin
52 | Export-Package: org.scalaide.play2,org.scalaide.play2.lexical,org.scal
53 | aide.play2.properties,org.scalaide.play2.quickassist,org.scalaide.pla
54 | y2.routeeditor,org.scalaide.play2.routeeditor.completion,org.scalaide
55 | .play2.routeeditor.completion.action,org.scalaide.play2.routeeditor.f
56 | ormatter,org.scalaide.play2.routeeditor.handlers,org.scalaide.play2.r
57 | outeeditor.hyperlink,org.scalaide.play2.routeeditor.lexical,org.scala
58 | ide.play2.routeeditor.properties,org.scalaide.play2.templateeditor,or
59 | g.scalaide.play2.templateeditor.compiler,org.scalaide.play2.templatee
60 | ditor.completion,org.scalaide.play2.templateeditor.hyperlink,org.scal
61 | aide.play2.templateeditor.lexical,org.scalaide.play2.templateeditor.p
62 | roperties,org.scalaide.play2.templateeditor.reconciler,org.scalaide.p
63 | lay2.templateeditor.sse,org.scalaide.play2.templateeditor.sse.hyperli
64 | nk,org.scalaide.play2.templateeditor.sse.lexical,org.scalaide.play2.t
65 | emplateeditor.sse.model,org.scalaide.play2.templateeditor.sse.style,o
66 | rg.scalaide.play2.templateeditor.sse.validation,org.scalaide.play2.ut
67 | il,org.scalaide.play2.wizards,org.scalaide.play2.templateeditor.proce
68 | ssing
69 |
--------------------------------------------------------------------------------
/org.scala-ide.play2/about.ini:
--------------------------------------------------------------------------------
1 | # Property "featureImage" contains path to feature image (32x32)
2 | featureImage=about.png
3 | aboutText=Play 2 Support for Scala IDE\n\
4 | (c) Typesafe\n\
5 | \n\
6 | Play 2 Support for Scala IDE provides editor for route file and template files.\n\
7 | Visit https://github.com/scala-ide/scala-ide-play2/wiki/Documentation\n\n\
8 | Typesafe Team: Amir Shaikhha, Luc Bourlier, Mirco Dotta, and Iulian Dragos.\n\
9 |
--------------------------------------------------------------------------------
/org.scala-ide.play2/about.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scala-ide/scala-ide-play2/d9c116f2c5e1e83b1093628395bc11e8dab377ac/org.scala-ide.play2/about.png
--------------------------------------------------------------------------------
/org.scala-ide.play2/build.properties:
--------------------------------------------------------------------------------
1 | source.. = src/
2 | output.. = target/classes/
3 | bin.includes = META-INF/,\
4 | .,\
5 | plugin.xml,\
6 | plugin.properties,\
7 | icons/,\
8 | about.ini,\
9 | about.png,\
10 |
--------------------------------------------------------------------------------
/org.scala-ide.play2/icons/newtemplate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scala-ide/scala-ide-play2/d9c116f2c5e1e83b1093628395bc11e8dab377ac/org.scala-ide.play2/icons/newtemplate.png
--------------------------------------------------------------------------------
/org.scala-ide.play2/icons/pin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scala-ide/scala-ide-play2/d9c116f2c5e1e83b1093628395bc11e8dab377ac/org.scala-ide.play2/icons/pin.png
--------------------------------------------------------------------------------
/org.scala-ide.play2/icons/play.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scala-ide/scala-ide-play2/d9c116f2c5e1e83b1093628395bc11e8dab377ac/org.scala-ide.play2/icons/play.png
--------------------------------------------------------------------------------
/org.scala-ide.play2/icons/routes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scala-ide/scala-ide-play2/d9c116f2c5e1e83b1093628395bc11e8dab377ac/org.scala-ide.play2/icons/routes.png
--------------------------------------------------------------------------------
/org.scala-ide.play2/icons/sample.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scala-ide/scala-ide-play2/d9c116f2c5e1e83b1093628395bc11e8dab377ac/org.scala-ide.play2/icons/sample.gif
--------------------------------------------------------------------------------
/org.scala-ide.play2/icons/web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scala-ide/scala-ide-play2/d9c116f2c5e1e83b1093628395bc11e8dab377ac/org.scala-ide.play2/icons/web.png
--------------------------------------------------------------------------------
/org.scala-ide.play2/plugin.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scala-ide/scala-ide-play2/d9c116f2c5e1e83b1093628395bc11e8dab377ac/org.scala-ide.play2/plugin.properties
--------------------------------------------------------------------------------
/org.scala-ide.play2/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.scala-ide
7 | org.scala-ide.play2.build
8 | 0.11.0-SNAPSHOT
9 |
10 | org.scala-ide.play2
11 | eclipse-plugin
12 |
13 |
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/IssueTracker.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2
2 |
3 | object IssueTracker {
4 | final val Url: String = "https://github.com/scala-ide/scala-ide-play2/issues"
5 |
6 | def createATicketMessage: String = s"This is a bug. Please, file a ticket at ${Url}."
7 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/PlayClassNames.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2
2 |
3 | trait PlayClassNames {
4 | protected def controllerClassFullName: String
5 | protected def actionClassFullName: String
6 | }
7 |
8 | object ScalaPlayClassNames {
9 | final val ControllerClassFullName = "play.api.mvc.Controller"
10 | final val ActionClassFullName = "play.api.mvc.EssentialAction"
11 | }
12 |
13 | trait ScalaPlayClassNames extends PlayClassNames {
14 | override protected def controllerClassFullName: String = ScalaPlayClassNames.ControllerClassFullName
15 | override protected def actionClassFullName: String = ScalaPlayClassNames.ActionClassFullName
16 | }
17 |
18 | object JavaPlayClassNames {
19 | final val ControllerClassFullName = "play.mvc.Controller"
20 | final val ActionClassFullName = "play.mvc.Result"
21 | }
22 |
23 | trait JavaPlayClassNames extends PlayClassNames {
24 | override protected def controllerClassFullName: String = JavaPlayClassNames.ControllerClassFullName
25 | override protected def actionClassFullName: String = JavaPlayClassNames.ActionClassFullName
26 |
27 | private final def unresolvedActionClassName: String = "QResult;"
28 | private final def resolvedBinaryFullActionClassName: String = "Lplay/mvc/Result;"
29 |
30 | final protected def allActionClassNameCandidates: Set[String] = Set(unresolvedActionClassName, resolvedBinaryFullActionClassName)
31 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/PlayPlugin.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2
2 |
3 | import org.scalaide.core.IScalaPlugin
4 | import org.eclipse.core.resources.IProject
5 | import org.eclipse.core.resources.ResourcesPlugin
6 | import org.eclipse.core.runtime.Status
7 | import org.eclipse.jface.preference.IPreferenceStore
8 | import org.eclipse.jface.resource.ImageDescriptor
9 | import org.eclipse.ui.plugin.AbstractUIPlugin
10 | import org.osgi.framework.BundleContext
11 | import org.eclipse.jface.resource.ImageRegistry
12 | import org.scalaide.play2.util.Images
13 |
14 | object PlayPlugin {
15 | @volatile
16 | private var plugin: PlayPlugin = _
17 |
18 | final val PluginId = "org.scala-ide.play2"
19 | final val RouteFormatterMarginId = PluginId + ".routeeditor.margin"
20 | final val RouteFormatterFormatOnSaveId = PluginId + ".routeeditor.formatonsave"
21 | final val TemplateExtension = "scala.html"
22 |
23 | /** Return the current plugin instace */
24 | def instance(): PlayPlugin = plugin
25 |
26 | /** Return the plugin-wide preference store */
27 | def preferenceStore: IPreferenceStore = plugin.getPreferenceStore
28 |
29 | def getImageDescriptor(path: String): ImageDescriptor = {
30 | AbstractUIPlugin.imageDescriptorFromPlugin(PluginId, path);
31 | }
32 |
33 | def log(status: Int, msg: String, ex: Throwable = null): Unit = {
34 | plugin.getLog.log(new Status(status, plugin.getBundle().getSymbolicName(), msg, ex))
35 | }
36 | }
37 |
38 | class PlayPlugin extends AbstractUIPlugin {
39 | override def start(context: BundleContext): Unit = {
40 | super.start(context)
41 | PlayPlugin.plugin = this
42 | initializeProjects()
43 | }
44 |
45 | override def stop(context: BundleContext): Unit = {
46 | PlayPlugin.plugin = null
47 | super.stop(context)
48 | }
49 |
50 | def asPlayProject(project: IProject): Option[PlayProject] = {
51 | val scalaProject = IScalaPlugin().asScalaProject(project)
52 | scalaProject map (PlayProject(_))
53 | }
54 |
55 | private def initializeProjects(): Unit = {
56 | for {
57 | iProject <- ResourcesPlugin.getWorkspace.getRoot.getProjects
58 | if iProject.isOpen
59 | playProject <- asPlayProject(iProject)
60 | } playProject.initialize()
61 | }
62 |
63 | override def initializeImageRegistry(reg: ImageRegistry) {
64 | reg.put(Images.ROUTES_ICON, Images.ROUTES_ICON_DESCRIPTOR)
65 | reg.put(Images.HTTP_METHODS_ICON, Images.HTTP_METHODS_ICON_DESCRIPTOR)
66 | reg.put(Images.URL_ICON, Images.URL_ICON_DESCRIPTOR)
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/PlayProject.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2
2 |
3 | import scala.collection.mutable
4 |
5 | import org.eclipse.core.resources.IFile
6 | import org.eclipse.core.resources.ProjectScope
7 | import org.eclipse.jface.preference.IPreferenceStore
8 | import org.eclipse.ui.preferences.ScopedPreferenceStore
9 | import org.scalaide.core.IScalaProject
10 | import org.scalaide.play2.properties.PlayPreferences
11 | import org.scalaide.play2.templateeditor.TemplateCompilationUnit
12 | import org.scalaide.play2.util.SyncedScopedPreferenceStore
13 |
14 | class PlayProject private (val scalaProject: IScalaProject) {
15 | val cachedPreferenceStore = new SyncedScopedPreferenceStore(scalaProject.underlying, PlayPlugin.PluginId)
16 |
17 | /**
18 | * Return additional imports that are automatically added to template files.
19 | *
20 | * @return The additional imports, or the empty string if none defined.
21 | */
22 | def templateImports(extension: String): String = {
23 | import org.scalaide.play2.properties.PlayPreferences._
24 | (defaultImports + cachedPreferenceStore.getString(TemplateImports)).replace("%format%", extension)
25 | }
26 |
27 | /** Return a new project-scoped preference store for this project. */
28 | def generateScopedPreferenceStore: IPreferenceStore = new ScopedPreferenceStore(new ProjectScope(scalaProject.underlying), PlayPlugin.PluginId)
29 |
30 | /**
31 | * Tries to load the scala template files
32 | */
33 | def initialize() {
34 | val templateCompilationUnits = for (
35 | r <- scalaProject.underlying.members() if r.isInstanceOf[IFile] && r.getFullPath().toString().endsWith("." + PlayPlugin.TemplateExtension)
36 | ) yield TemplateCompilationUnit(r.asInstanceOf[IFile], false)
37 | templateCompilationUnits foreach (_.initialReconcile())
38 | // TODO: Why was there a second round of ask reload here?
39 | // templateCompilationUnits.reverse foreach (_.askReload())
40 | }
41 |
42 | /**
43 | * FIXME: This method should probably not exist.
44 | * Template files can be anywhere
45 | *
46 | * @return the absolute location of the project directory
47 | */
48 | lazy val sourceDir = scalaProject.underlying.getLocation().toFile()
49 | }
50 |
51 | object PlayProject {
52 | private val projects = (new mutable.HashMap) withDefault { (scalaProject: IScalaProject) => new PlayProject(scalaProject) }
53 | def apply(scalaProject: IScalaProject): PlayProject = {
54 | projects(scalaProject)
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/lexical/PlayPartitionTokeniser.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.lexical
2 |
3 | import org.eclipse.jface.text.TypedRegion
4 | import org.eclipse.jface.text.IDocument
5 | /**
6 | * Interface for tokeniser
7 | */
8 | trait PlayPartitionTokeniser {
9 | def tokenise(document: IDocument): List[TypedRegion]
10 | }
11 |
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/properties/PlayPreferences.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.properties
2 |
3 | import org.eclipse.swt.SWT
4 | import org.eclipse.swt.widgets.Composite
5 | import org.eclipse.swt.widgets.Control
6 | import org.eclipse.ui.IWorkbench
7 | import org.eclipse.ui.IWorkbenchPreferencePage
8 | import org.eclipse.ui.dialogs.PropertyPage
9 |
10 | object PlayPreferences {
11 |
12 | /**
13 | * Preference containing the list of import to automatically add to the generate template code.
14 | * The data is stored as the string which will be added to the generated source (to not recreate
15 | * it everytime). The empty String represent an empty import list.
16 | * [[org.scalaide.play2.properties.PlayPreferences.serializeImports]] and [[org.scalaide.play2.properties.PlayPreferences.deserializeImports]]
17 | * need to be used when converting the preference value to/from Array[String].
18 | */
19 | final val TemplateImports = "templateImports"
20 |
21 | final val DefaultTemplateImports = List(
22 | "models._",
23 | "controllers._",
24 | "play.api.i18n._",
25 | "play.api.mvc._",
26 | "play.api.data._",
27 | "views.%format%._",
28 | "play.api.templates.PlayMagic._",
29 | "play.mvc.Http.Context.Implicit._")
30 |
31 | final val defaultImports = serializeImports(DefaultTemplateImports.toArray)
32 |
33 | final val PlayVersion = "playVersion"
34 |
35 | final val PlaySupportedVersion = List("2.6", "2.5")
36 |
37 | final val DefaultPlayVersion = PlaySupportedVersion.head
38 |
39 | // Regex used for the operations on the templateImports preference.
40 | private val importsRegex = "import ([^\n]+)\n".r
41 |
42 | /**
43 | * @see [[org.scalaide.play2.properties.PlayPreferences.TemplateImports]]
44 | */
45 | def serializeImports(entries: Array[String]): String = {
46 | if (entries.length == 0) {
47 | ""
48 | } else {
49 | entries.mkString("import ", "\nimport ", "\n")
50 | }
51 | }
52 |
53 | /**
54 | * @see [[org.scalaide.play2.properties.PlayPreferences.TemplateImports]]
55 | */
56 | def deserializeImports(s: String): Array[String] = {
57 | if (s.length == 0) {
58 | new Array(0)
59 | } else {
60 | importsRegex.findAllIn(s).matchData.map(m => m.group(1)).toArray
61 | }
62 | }
63 |
64 | }
65 |
66 | /** An empty preference page, used as an intermediary node under the Play page. */
67 | class PlayPreferences extends PropertyPage with IWorkbenchPreferencePage {
68 | override def createContents(parent: Composite): Control = {
69 | new Composite(parent, SWT.NULL)
70 | }
71 |
72 | override def init(workbench: IWorkbench): Unit = {}
73 | }
74 |
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/properties/PreferenceInitializer.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.properties
2 |
3 | import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer
4 | import org.scalaide.play2.PlayPlugin
5 |
6 | class PreferenceInitializer extends AbstractPreferenceInitializer {
7 | import PlayPreferences._
8 |
9 | override def initializeDefaultPreferences(): Unit = {
10 | PlayPlugin.preferenceStore.setDefault(PlayVersion, DefaultPlayVersion)
11 | PlayPlugin.preferenceStore.setDefault(TemplateImports, "")
12 | }
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/properties/ProjectPropertyPage.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.properties
2 |
3 | import org.eclipse.core.resources.IProject
4 | import org.eclipse.core.runtime.IAdaptable
5 | import org.eclipse.jdt.core.IJavaProject
6 | import org.eclipse.jface.dialogs.IInputValidator
7 | import org.eclipse.jface.dialogs.InputDialog
8 | import org.eclipse.jface.preference.FieldEditorPreferencePage
9 | import org.eclipse.jface.preference.IPreferenceStore
10 | import org.eclipse.jface.preference.ListEditor
11 | import org.eclipse.jface.window.Window
12 | import org.eclipse.swt.widgets.Composite
13 | import org.eclipse.swt.widgets.Display
14 | import org.eclipse.ui.IWorkbenchPropertyPage
15 | import org.scalaide.play2.PlayPlugin
16 |
17 | /**
18 | * Preference page displayed in the property dialog of (play) projects.
19 | * Used from the UI thread.
20 | */
21 | class ProjectPropertyPage extends FieldEditorPreferencePage(FieldEditorPreferencePage.GRID) with IWorkbenchPropertyPage {
22 |
23 | /**
24 | * Preference field to display the list of extra imports.
25 | */
26 | private class ImportsFieldEditor(name: String, labelText: String, parent: Composite) extends ListEditor(name, labelText, parent) {
27 |
28 | override protected def createList(entries: Array[String]): String =
29 | PlayPreferences.serializeImports(entries)
30 |
31 | override protected def parseString(s: String): Array[String] =
32 | PlayPreferences.deserializeImports(s)
33 |
34 | override protected def getNewInputObject(): String = {
35 |
36 | val dlg = new InputDialog(
37 | Display.getCurrent().getActiveShell(),
38 | "Play template import",
39 | "Enter an import value:",
40 | "com.example._",
41 | new IInputValidator {
42 | def isValid(text: String) = null
43 | });
44 |
45 | if (dlg.open() == Window.OK) {
46 | dlg.getValue()
47 | } else {
48 | null
49 | }
50 | }
51 |
52 | }
53 |
54 | // The preference store being edited.
55 | // The data require to get the store is provided by the workbench during the page lifecycle.
56 | private var prefStore: IPreferenceStore = _
57 |
58 | // Members declared in org.eclipse.jface.preference.FieldEditorPreferencePage
59 |
60 | override def createFieldEditors() {
61 | addField(new ProjectPropertyPage.PlayProjectVersion(getFieldEditorParent()))
62 | addField(new ImportsFieldEditor(PlayPreferences.TemplateImports, "Template default imports", getFieldEditorParent()))
63 | }
64 |
65 | // Members declared in org.eclipse.ui.IWorkbenchPropertyPage
66 |
67 | // doesn't seem to be a real function for this method.
68 | // It looks like it leaked from the implementation of PropertyPage.
69 | override def getElement(): IAdaptable = null
70 |
71 | override def setElement(element: IAdaptable) {
72 | prefStore = element match {
73 | case project: IProject =>
74 | PlayPlugin.instance().asPlayProject(project).get.generateScopedPreferenceStore
75 | case project: IJavaProject =>
76 | PlayPlugin.instance().asPlayProject(project.getProject()).get.generateScopedPreferenceStore
77 | }
78 | }
79 |
80 | override def doGetPreferenceStore(): IPreferenceStore =
81 | prefStore
82 | }
83 |
84 | object ProjectPropertyPage {
85 | import org.eclipse.jface.preference.ComboFieldEditor
86 | import org.scalaide.play2.properties.PlayPreferences._
87 |
88 | private def supportedVersions = PlaySupportedVersion.map(version => Array(version, version)).toArray
89 |
90 | class PlayProjectVersion(parent: Composite) extends ComboFieldEditor(PlayVersion, "Play version", supportedVersions, parent)
91 | }
92 |
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/quickassist/AddRouteEntryProposal.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.quickassist
2 |
3 | import org.eclipse.jface.text.IDocument
4 |
5 | import org.eclipse.swt.graphics.Image
6 | import org.scalaide.core.internal.statistics.Features.Feature
7 | import org.scalaide.core.internal.statistics.Groups.Editing
8 | import org.scalaide.core.quickassist.BasicCompletionProposal
9 |
10 | object AddRouteEntry extends Feature("AddRouteEntry")("Add entry to route file", Editing)
11 |
12 | case class AddRouteEntryProposal(display: String, image: Image = null)(f: IDocument => Unit) extends BasicCompletionProposal(AddRouteEntry, 100, display, image) {
13 | override def applyProposal(doc: IDocument) = f(doc)
14 | }
15 |
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/quickassist/ControllerMethod.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.quickassist
2 |
3 | /** A controller method definition, with helper methods to generate the route-file
4 | * syntax.
5 | */
6 | case class ControllerMethod(typeName: String, methodName: String, params: List[(String, String)]) {
7 | import ControllerMethod._
8 |
9 | def fullName: String =
10 | "%s.%s".format(typeName, methodName)
11 |
12 | /** Return the route-call syntax, simplifying types if possible.
13 | *
14 | * A parameter of type String is omitted, and primitive types are stripped the
15 | * `scala` package prefix.
16 | *
17 | * @see http://www.playframework.com/documentation/2.1.1/ScalaRouting
18 | */
19 | def toRouteCallSyntax: String = {
20 | val parts = for ((name, tpe) <- params) yield simplifyType(tpe) match {
21 | case None => name
22 | case Some(simpleTpe) => s"$name: $simpleTpe"
23 | }
24 |
25 | s"$fullName(${parts.mkString(", ")})"
26 | }
27 | }
28 |
29 | object ControllerMethod {
30 | /** Map a type to a pretty name to use in the route file.
31 | * Strings are mapped to the empty string
32 | */
33 | private val simplifyType = Map(
34 | "java.lang.String" -> None,
35 | "scala.String" -> None,
36 | "String" -> None,
37 | "scala.Boolean" -> Some("Boolean"),
38 | "scala.Byte" -> Some("Byte"),
39 | "scala.Short" -> Some("Short"),
40 | "scala.Char" -> Some("Char"),
41 | "scala.Int" -> Some("Int"),
42 | "scala.Long" -> Some("Long"),
43 | "scala.Float" -> Some("Float"),
44 | "scala.Double" -> Some("Double"),
45 |
46 | // Java types
47 | "boolean" -> Some("Boolean"),
48 | "byte" -> Some("Byte"),
49 | "short" -> Some("Short"),
50 | "char" -> Some("Char"),
51 | "int" -> Some("Int"),
52 | "long" -> Some("Long"),
53 | "float" -> Some("Float"),
54 | "double" -> Some("Double")) withDefault (Some.apply)
55 |
56 | private val FullNameRegex = """(.+)\.([^.]+)""".r
57 |
58 | /** Create a new instance by extracting the type and the method name.
59 | */
60 | def apply(fullName: String, params: List[(String, String)]): ControllerMethod =
61 | fullName match {
62 | case FullNameRegex(typeName, methodName) =>
63 | new ControllerMethod(typeName, methodName, params)
64 | case _ =>
65 | throw new IllegalArgumentException(s"'$fullName' cannot be parsed as a full method name")
66 | }
67 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/routeeditor/EditorMessages.properties:
--------------------------------------------------------------------------------
1 | Editor.Format.label=&Format
2 | Editor.Format.tooltip=Format the Selected Text
3 | Editor.Format.description=Format the Selected Text
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/routeeditor/EditorMessages.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.routeeditor
2 |
3 | import java.util.ResourceBundle
4 |
5 | /**
6 | * Manage the NLSed data. Needed for the editor actions.
7 | */
8 | object EditorMessages {
9 | lazy val resourceBundle= ResourceBundle.getBundle("org.scalaide.play2.routeeditor.EditorMessages")
10 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/routeeditor/HasScalaProject.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.routeeditor
2 |
3 | import org.scalaide.core.IScalaProject
4 |
5 | /** @note This marker trait should be moved in the scala-ide sdt.core bundle. */
6 | trait HasScalaProject {
7 | def getScalaProject: Option[IScalaProject]
8 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/routeeditor/RouteAction.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.routeeditor
2 |
3 | import org.eclipse.jface.text.IDocument
4 | import org.scalaide.play2.routeeditor.lexical.RoutePartitions
5 | import org.eclipse.jface.text.IRegion
6 | import org.scalaide.play2.quickassist.ControllerMethod
7 |
8 | object RouteAction {
9 |
10 | /** Regex for the an action with parameters.
11 | * "package.Object.action(...xxx...)"
12 | * or
13 | * "@package.Class.action(...xxx...)"
14 | */
15 | private final val ActionWithParametersRegex = """@?([^\(]*)\.([^\.\(]*)\(([^\)]*)\)""".r
16 |
17 | /** Regex for the an action without parameters.
18 | * "package.Object.action"
19 | * or
20 | * "@package.Class.action"
21 | */
22 | private final val ActionWithoutParametersRegex = """@?([^\(]*)\.([^\.\(]*)""".r
23 |
24 | /** Regex for the individual parameters.
25 | * The support format is: "page: Int ?= 1"
26 | */
27 | private final val ParameterWithTypeRegex = """(.*):([^\?]*)(\?=.*)?""".r
28 |
29 | private final val ParameterWithoutTypeRegex = """([^\?]*)(\?=.*)?""".r
30 |
31 | /** Return the route action description at the location, using the document
32 | * partitions.
33 | */
34 | def routeActionAt(document: IDocument, offset: Int): Option[RouteAction] = {
35 | val partition = document.getPartition(offset)
36 | if (RoutePartitions.isRouteAction(partition.getType())) {
37 | document.get(partition.getOffset(), partition.getLength()) match {
38 | case ActionWithoutParametersRegex(typeName, methodName) =>
39 | Some(new RouteAction(typeName, methodName, Nil, partition))
40 | case ActionWithParametersRegex(typeName, methodName, parameters) =>
41 | Some(new RouteAction(typeName, methodName, parseParameterTypes(parameters), partition))
42 | case s =>
43 | None
44 | }
45 | } else {
46 | None
47 | }
48 | }
49 |
50 | private def parseParameterTypes(parameters: String): List[(String, String)] = {
51 | if (parameters.isEmpty()) {
52 | Nil
53 | } else {
54 | parameters.split(",").toList.map {
55 | case ParameterWithTypeRegex(name, tpe, _) =>
56 | (name.trim, tpe.trim)
57 | case ParameterWithoutTypeRegex(name, _) =>
58 | // if the type is not specified, the default is String
59 | (name.trim, "String")
60 | }
61 | }
62 | }
63 |
64 | }
65 |
66 | /** Description of an action in a route file.
67 | */
68 | class RouteAction(typeName: String, methodName: String, params: List[(String, String)], val region: IRegion) extends ControllerMethod(typeName, methodName, params)
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/routeeditor/RouteConfiguration.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.routeeditor
2 |
3 | import org.eclipse.jface.preference.IPreferenceStore
4 | import org.eclipse.jface.text.IDocument
5 | import org.eclipse.jface.text.contentassist.ContentAssistant
6 | import org.eclipse.jface.text.contentassist.IContentAssistant
7 | import org.eclipse.jface.text.formatter.MultiPassContentFormatter
8 | import org.eclipse.jface.text.hyperlink.IHyperlinkDetector
9 | import org.eclipse.jface.text.presentation.IPresentationReconciler
10 | import org.eclipse.jface.text.source.ISourceViewer
11 | import org.eclipse.jface.text.source.SourceViewerConfiguration
12 | import org.eclipse.jface.util.PropertyChangeEvent
13 | import org.scalaide.play2.routeeditor.completion.ActionContentAssistProcessor
14 | import org.scalaide.play2.routeeditor.completion.HttpMethodCompletionComputer
15 | import org.scalaide.play2.routeeditor.completion.UriCompletionComputer
16 | import org.scalaide.play2.routeeditor.formatter.RouteFormattingStrategy
17 | import org.scalaide.play2.routeeditor.hyperlink.RouteHyperlinkDetector
18 | import org.scalaide.play2.routeeditor.lexical.RoutePartitions
19 | import org.eclipse.jface.util.IPropertyChangeListener
20 |
21 | class RouteConfiguration(prefStore: IPreferenceStore, routeEditor: RouteEditor) extends SourceViewerConfiguration with IPropertyChangeListener {
22 | private val reconciler: RoutePresentationReconciler = new RoutePresentationReconciler(prefStore)
23 |
24 | override def getDoubleClickStrategy(sourceViewer: ISourceViewer, contentType: String) = {
25 | new RouteDoubleClickStrategy()
26 | }
27 |
28 | override def getConfiguredContentTypes(sourceViewer: ISourceViewer) = {
29 | RoutePartitions.getTypes
30 | }
31 |
32 | override def getContentAssistant(sourceViewer: ISourceViewer): IContentAssistant = {
33 | val assistant = new ContentAssistant
34 | assistant.setAutoActivationDelay(50)
35 | assistant.enableAutoActivation(true)
36 | assistant.setDocumentPartitioning(getConfiguredDocumentPartitioning(sourceViewer))
37 | assistant.setContentAssistProcessor(new HttpMethodCompletionComputer, RoutePartitions.ROUTE_HTTP)
38 | assistant.setContentAssistProcessor(new UriCompletionComputer, RoutePartitions.ROUTE_URI)
39 | assistant.setContentAssistProcessor(new ActionContentAssistProcessor(routeEditor), RoutePartitions.ROUTE_ACTION)
40 | assistant
41 | }
42 |
43 | override def getHyperlinkDetectors(sourceViewer: ISourceViewer): Array[IHyperlinkDetector] = Array(new RouteHyperlinkDetector(routeEditor))
44 |
45 | override def getPresentationReconciler(sourceViewer: ISourceViewer): IPresentationReconciler = reconciler
46 |
47 | override def getContentFormatter(viewer: ISourceViewer) = {
48 | val formatter = new MultiPassContentFormatter(getConfiguredDocumentPartitioning(viewer), IDocument.DEFAULT_CONTENT_TYPE)
49 | formatter.setMasterStrategy(new RouteFormattingStrategy(routeEditor))
50 | formatter
51 | }
52 |
53 | override def propertyChange(event: PropertyChangeEvent): Unit = {
54 | reconciler.propertyChange(event)
55 | }
56 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/routeeditor/RouteDocumentProvider.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.routeeditor
2 |
3 | import org.eclipse.jface.text.IDocument
4 | import org.eclipse.ui.editors.text.FileDocumentProvider
5 | import org.scalaide.play2.routeeditor.lexical.RouteDocumentPartitioner
6 |
7 | class RouteDocumentProvider extends FileDocumentProvider {
8 | override protected def createDocument(element: Object): IDocument = {
9 | val document = super.createDocument(element);
10 | if (document != null) {
11 | val partitioner = new RouteDocumentPartitioner()
12 | partitioner.connect(document)
13 | document.setDocumentPartitioner(partitioner)
14 | }
15 | document
16 | }
17 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/routeeditor/RouteDoubleClickStrategy.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.routeeditor
2 |
3 | import org.eclipse.jface.text.DefaultTextDoubleClickStrategy
4 |
5 | class RouteDoubleClickStrategy extends DefaultTextDoubleClickStrategy
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/routeeditor/RoutePresentationReconciler.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.routeeditor
2 |
3 | import org.eclipse.jface.preference.IPreferenceStore
4 | import org.eclipse.jface.text.presentation.PresentationReconciler
5 | import org.eclipse.jface.text.rules.DefaultDamagerRepairer
6 | import org.eclipse.jface.text.rules.ITokenScanner
7 | import org.eclipse.jface.util.PropertyChangeEvent
8 | import org.scalaide.play2.routeeditor.lexical.RouteActionScanner
9 | import org.scalaide.play2.routeeditor.lexical.RoutePartitions
10 | import org.scalaide.play2.routeeditor.lexical.RouteURIScanner
11 | import org.eclipse.jface.util.IPropertyChangeListener
12 | import org.scalaide.core.lexical.ScalaCodeScanners
13 |
14 | class RoutePresentationReconciler(prefStore: IPreferenceStore) extends PresentationReconciler with IPropertyChangeListener {
15 |
16 | private val scanner =
17 | ScalaCodeScanners.singleTokenScanner(prefStore, RouteSyntaxClasses.DEFAULT)
18 |
19 | private val httpScanner =
20 | ScalaCodeScanners.singleTokenScanner(prefStore, RouteSyntaxClasses.HTTP_KEYWORD)
21 |
22 | private val uriScanner =
23 | new RouteURIScanner(prefStore)
24 |
25 | private val actionScanner =
26 | new RouteActionScanner(prefStore)
27 |
28 | private val commentScanner =
29 | ScalaCodeScanners.singleTokenScanner(prefStore, RouteSyntaxClasses.COMMENT)
30 |
31 | handlePartition(scanner, RoutePartitions.ROUTE_DEFAULT)
32 | handlePartition(httpScanner, RoutePartitions.ROUTE_HTTP)
33 | handlePartition(uriScanner, RoutePartitions.ROUTE_URI)
34 | handlePartition(actionScanner, RoutePartitions.ROUTE_ACTION)
35 | handlePartition(commentScanner, RoutePartitions.ROUTE_COMMENT)
36 |
37 | private def handlePartition(scan: ITokenScanner, token: String) = {
38 | val dr = new DefaultDamagerRepairer(scan);
39 | setDamager(dr, token)
40 | setRepairer(dr, token)
41 | }
42 |
43 | override def propertyChange(event: PropertyChangeEvent) {
44 | scanner.adaptToPreferenceChange(event)
45 | httpScanner.adaptToPreferenceChange(event)
46 | uriScanner.adaptToPreferenceChange(event)
47 | actionScanner.adaptToPreferenceChange(event)
48 | commentScanner.adaptToPreferenceChange(event)
49 | }
50 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/routeeditor/RouteSyntaxClasses.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.routeeditor
2 |
3 | import org.scalaide.ui.syntax.ScalaSyntaxClass
4 | import org.scalaide.ui.syntax.ScalaSyntaxClass.Category
5 |
6 | object RouteSyntaxClasses {
7 | val DEFAULT = ScalaSyntaxClass("Default", "route.default")
8 | val COMMENT = ScalaSyntaxClass("Comment", "route.comment")
9 | val URI = ScalaSyntaxClass("URI", "route.uri")
10 | val URI_DYNAMIC = ScalaSyntaxClass("URI Dynamic", "route.uriDynamic")
11 | val ACTION = ScalaSyntaxClass("Action", "route.action")
12 | val ACTION_PACKAGE = ScalaSyntaxClass("Action package", "route.actionPackage")
13 | val ACTION_CLASS = ScalaSyntaxClass("Action class", "route.actionClass")
14 | val ACTION_METHOD = ScalaSyntaxClass("Action method name", "route.actionMethod")
15 | val HTTP_KEYWORD = ScalaSyntaxClass("HTTP keyword", "route.httpKeyword")
16 |
17 | val routeURICategory = Category("URI", List(
18 | URI, URI_DYNAMIC))
19 |
20 | val routeActionCategory = Category("Action", List(
21 | ACTION, ACTION_PACKAGE, ACTION_CLASS, ACTION_METHOD))
22 |
23 | val routeOtherCategory = Category("Other", List(
24 | DEFAULT, COMMENT, HTTP_KEYWORD))
25 |
26 | val categories = List(routeURICategory, routeActionCategory, routeOtherCategory)
27 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/routeeditor/completion/ActionContentAssistProcessor.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.routeeditor.completion
2 |
3 | import org.scalaide.core.IScalaProject
4 | import org.scalaide.logging.HasLogger
5 |
6 | import org.eclipse.jface.text.ITextViewer
7 | import org.eclipse.jface.text.contentassist.ICompletionProposal
8 | import org.eclipse.jface.text.contentassist.IContentAssistProcessor
9 | import org.eclipse.jface.text.contentassist.IContextInformation
10 | import org.scalaide.play2.routeeditor.HasScalaProject
11 | import org.scalaide.play2.routeeditor.completion.action.ActionCompletionComputer
12 |
13 | class ActionContentAssistProcessor(routeEditor: HasScalaProject) extends IContentAssistProcessor with HasLogger {
14 |
15 | override def getCompletionProposalAutoActivationCharacters(): Array[Char] = Array('.')
16 |
17 | override def getContextInformationAutoActivationCharacters(): Array[Char] = null
18 |
19 | override def getErrorMessage = null
20 |
21 | override def getContextInformationValidator = null
22 |
23 | override def computeCompletionProposals(viewer: ITextViewer, offset: Int): Array[ICompletionProposal] = {
24 | val proposals = {
25 | for (project <- routeEditor.getScalaProject)
26 | yield computeCompletionProposals(project, viewer, offset)
27 | }
28 | proposals getOrElse null
29 | }
30 |
31 | private def computeCompletionProposals(project: IScalaProject, viewer: ITextViewer, offset: Int): Array[ICompletionProposal] = {
32 | val document = viewer.getDocument
33 |
34 | import org.scalaide.core.compiler.IScalaPresentationCompiler.Implicits._
35 | val completions = project.presentationCompiler { compiler =>
36 | compiler.asyncExec {
37 | val actionComputer = new ActionCompletionComputer(compiler)
38 | actionComputer.computeCompletionProposals(document, offset)
39 | }.getOrElse(Nil)()
40 | } getOrElse Nil
41 |
42 | completions.sorted.toArray
43 | }
44 |
45 | override def computeContextInformation(viewer: ITextViewer, offset: Int): Array[IContextInformation] = {
46 | null
47 | }
48 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/routeeditor/completion/HttpMethodsCompletionComputer.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.routeeditor.completion
2 |
3 | import org.eclipse.jface.text.IDocument
4 | import org.eclipse.jface.text.IRegion
5 | import org.eclipse.jface.text.ITextViewer
6 | import org.eclipse.jface.text.contentassist.ICompletionProposal
7 | import org.eclipse.jface.text.contentassist.IContentAssistProcessor
8 | import org.eclipse.jface.text.contentassist.IContextInformation
9 | import org.eclipse.swt.graphics.Image
10 | import org.eclipse.swt.graphics.Point
11 | import org.scalaide.ui.editor.WordFinder
12 | import org.scalaide.play2.PlayPlugin
13 | import org.scalaide.play2.routeeditor.lexical.HTTPKeywords
14 | import org.scalaide.play2.util.Images
15 |
16 | class HttpMethodCompletionComputer extends IContentAssistProcessor {
17 |
18 | override def getCompletionProposalAutoActivationCharacters(): Array[Char] = null
19 |
20 | override def getContextInformationAutoActivationCharacters(): Array[Char] = null
21 |
22 | override def getErrorMessage = null
23 |
24 | override def getContextInformationValidator = null
25 |
26 | override def computeCompletionProposals(viewer: ITextViewer, offset: Int): Array[ICompletionProposal] = {
27 | val region = WordFinder.findWord(viewer.getDocument(), offset)
28 | val input = viewer.getDocument().get(region.getOffset(), region.getLength()).toUpperCase
29 |
30 | val filteredCompletions = HTTPKeywords.Methods.filter(_.take(region.getLength) == input)
31 | val completions = {
32 | // If the `input` matches one of the valid HTTP methods, return full list of alternatives as the
33 | // user likely wants to change the current valid input with another one.
34 | if (HTTPKeywords.Methods.contains(input) || filteredCompletions.isEmpty) HTTPKeywords.Methods
35 | else filteredCompletions
36 | }
37 |
38 | completions.map(new HttpMethodCompletionProposal(region, _))
39 | }
40 |
41 | override def computeContextInformation(viewer: ITextViewer, offset: Int): Array[IContextInformation] = {
42 | null
43 | }
44 |
45 | private class HttpMethodCompletionProposal(region: IRegion, displayString: String) extends ICompletionProposal {
46 | override def apply(document: IDocument): Unit = {
47 | document.replace(region.getOffset, region.getLength, displayString)
48 | }
49 |
50 | override def getSelection(document: IDocument): Point =
51 | new Point(region.getOffset() + displayString.length, 0) // always put caret *after* the inserted completion
52 | override def getAdditionalProposalInfo: String = null
53 | override def getDisplayString: String = displayString
54 | override def getImage: Image = PlayPlugin.instance.getImageRegistry().get(Images.HTTP_METHODS_ICON)
55 | override def getContextInformation: IContextInformation = null
56 | }
57 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/routeeditor/completion/UriCompletionComputer.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.routeeditor.completion
2 |
3 | import org.eclipse.jface.text.IDocument
4 | import org.eclipse.jface.text.IRegion
5 | import org.eclipse.jface.text.ITextViewer
6 | import org.eclipse.jface.text.contentassist.ICompletionProposal
7 | import org.eclipse.jface.text.contentassist.IContentAssistProcessor
8 | import org.eclipse.jface.text.contentassist.IContextInformation
9 | import org.eclipse.swt.graphics.Image
10 | import org.eclipse.swt.graphics.Point
11 | import org.scalaide.ui.editor.WordFinder
12 | import org.scalaide.play2.PlayPlugin
13 | import org.scalaide.play2.routeeditor.lexical.RouteDocumentPartitioner
14 | import org.scalaide.play2.util.Images
15 | import org.scalaide.play2.routeeditor.RouteUri
16 | import org.scalaide.play2.routeeditor.RouteUriWithRegion
17 |
18 | class UriCompletionComputer extends IContentAssistProcessor {
19 |
20 | override def getCompletionProposalAutoActivationCharacters(): Array[Char] =
21 | Array('/')
22 |
23 | override def getContextInformationAutoActivationCharacters(): Array[Char] = null
24 |
25 | override def getErrorMessage = null
26 |
27 | override def getContextInformationValidator = null
28 |
29 | override def computeCompletionProposals(viewer: ITextViewer, offset: Int): Array[ICompletionProposal] = {
30 | val document = viewer.getDocument()
31 |
32 | val word = WordFinder.findWord(document, offset)
33 | // only consider the prefix (word to the left of caret)
34 | val rawUri = document.get(word.getOffset, (offset - word.getOffset()))
35 | val uri = RouteUri(rawUri)
36 |
37 | val existingUris = RouteUriWithRegion.existingUrisInDocument(document).filter(_ != uri)
38 |
39 | // If the `rawUri` is empty then add '/' to the returned set of proposals
40 | val defaultUriProposal = if (rawUri.isEmpty) Set(RouteUri("/")) else Set.empty
41 |
42 | val staticUrisProposals = {
43 | if (RouteUri(rawUri).isValid) existingUris.flatMap(_.subUrisStartingWith(rawUri))
44 | // If the `rawUri` isn't valid, then proposals will contain all possible valid permutations of existing URIs
45 | else existingUris.flatMap(_.subUrisStartingWith(""))
46 | }
47 |
48 | val dynamicUrisProposals = {
49 | // Add dynamics parts to the proposals only if completion happens on an empty URI or after a slash
50 | if (rawUri.isEmpty) RouteUri("/").dynamicUris
51 | else if (rawUri.last == '/') RouteUri(rawUri).dynamicUris
52 | else staticUrisProposals
53 | }
54 |
55 | val allUrisProposals = defaultUriProposal ++ staticUrisProposals ++ dynamicUrisProposals
56 |
57 | val sortedProposals = allUrisProposals.toList.sorted(RouteUri.AlphabeticOrder)
58 |
59 | sortedProposals.map(new UriCompletionProposal(word, _)).toArray
60 | }
61 |
62 | override def computeContextInformation(viewer: ITextViewer, offset: Int): Array[IContextInformation] = {
63 | null
64 | }
65 |
66 | private class UriCompletionProposal(region: IRegion, uri: RouteUri) extends ICompletionProposal {
67 | override def apply(document: IDocument): Unit = {
68 | document.replace(region.getOffset, region.getLength, getDisplayString)
69 | }
70 |
71 | override def getSelection(document: IDocument): Point =
72 | new Point(region.getOffset() + getDisplayString.length, 0) // always put caret *after* the inserted completion
73 | override def getAdditionalProposalInfo: String = null
74 | override def getDisplayString: String = uri.toString
75 | override def getImage: Image = PlayPlugin.instance.getImageRegistry().get(Images.URL_ICON)
76 | override def getContextInformation: IContextInformation = null
77 | }
78 | }
79 |
80 |
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/routeeditor/completion/action/ActionCompletionProposal.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.routeeditor.completion.action
2 |
3 | import org.scalaide.core.completion.MemberKind
4 | import org.scalaide.ui.completion.ScalaCompletionProposal
5 |
6 | import org.eclipse.jdt.internal.ui.JavaPluginImages
7 | import org.eclipse.jface.text.IDocument
8 | import org.eclipse.jface.text.IRegion
9 | import org.eclipse.jface.text.contentassist.ICompletionProposal
10 | import org.eclipse.jface.text.contentassist.IContextInformation
11 | import org.eclipse.swt.graphics.Image
12 | import org.eclipse.swt.graphics.Point
13 |
14 | /** Completion for action method in route file.
15 | *
16 | * @param replaceRegion The region in the document that will be replaced if this proposal is applied.
17 | * @param simpleName The name of a package, type or method.
18 | * @param kind The kind of member of this proposal, i.e., val, var, object, class, package, ...
19 | * @param isJava Is this completion for a Java member.
20 | */
21 | case class ActionCompletionProposal(replaceRegion: IRegion, val simpleName: String, val kind: MemberKind.Value, val isJava: Boolean)
22 | extends ICompletionProposal {
23 |
24 | import ActionCompletionProposal.javaFieldImage
25 |
26 | override def apply(document: IDocument): Unit = {
27 | document.replace(replaceRegion.getOffset, replaceRegion.getLength, simpleName)
28 | }
29 |
30 | override def getSelection(document: IDocument): Point =
31 | new Point(replaceRegion.getOffset + simpleName.length, 0) // always put caret *after* the inserted completion
32 |
33 | override def getAdditionalProposalInfo: String = null
34 | override def getDisplayString: String = simpleName
35 | override def getImage: Image = kind match {
36 | case MemberKind.Def => ScalaCompletionProposal.defImage
37 | case MemberKind.Class if !isJava => ScalaCompletionProposal.classImage
38 | case MemberKind.Class if isJava => ScalaCompletionProposal.javaClassImage
39 | case MemberKind.Object => ScalaCompletionProposal.objectImage
40 | case MemberKind.Package => ScalaCompletionProposal.packageImage
41 | case MemberKind.Val => ScalaCompletionProposal.valImage
42 | case MemberKind.Var => javaFieldImage
43 | case _ => ScalaCompletionProposal.valImage
44 | }
45 | override def getContextInformation: IContextInformation = null
46 |
47 | }
48 |
49 | object ActionCompletionProposal {
50 | private val javaFieldImage = JavaPluginImages.get(JavaPluginImages.IMG_FIELD_PUBLIC)
51 |
52 | implicit object ByKindAndAlphabetically extends Ordering[ActionCompletionProposal] {
53 | override def compare(x: ActionCompletionProposal, y: ActionCompletionProposal): Int = {
54 | /* If `kind` is a package, then only types and packages can be suggested to the user. In this case,
55 | * types should be shown before packages. The only other alternative is that `kind` is a member,
56 | * in this case sort the members alphabetically.
57 | */
58 | val compared = relevance(y) - relevance(x)
59 | if (compared == 0) x.simpleName.compareTo(y.simpleName) else compared
60 | }
61 |
62 | private def relevance(that: ActionCompletionProposal): Int = {
63 | if (that.kind == MemberKind.Package) 10
64 | else 100
65 | }
66 | }
67 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/routeeditor/completion/action/ActionRouteInput.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.routeeditor.completion.action
2 |
3 | /** A simple wrapper for parsing action method invocation in a route file.
4 | *
5 | * An action method invocation in a route file is a fully qualified method (of return type Action -
6 | * or Result, in Java), in a Play controller class.
7 | *
8 | * @param input The (possibly incomplete) action method invocation a route file.
9 | */
10 | private[action] class ActionRouteInput(input: String) {
11 |
12 | /** If the passed `fullName` starts with a '@', the controller class is instantiated by the framework.
13 | *
14 | * @see Section '''Managed Controller classes instantiation''' in http://www.playframework.com/documentation/2.1.1/Highlights
15 | * for more details.
16 | */
17 | def isControllerClassInstantiation: Boolean = input.startsWith("@")
18 |
19 | /** Returns the `input` without the leading '@', if present. */
20 | def fullName: String = {
21 | if (isControllerClassInstantiation) input.substring(1)
22 | else input
23 | }
24 |
25 | /** Returns the prefix of the action method invocation. Hence, a valid prefix is either a fully
26 | * qualified package (could also be the empty package) or a class.
27 | *
28 | * @note If present, the leading '@' is removed.
29 | */
30 | def prefix: String = fullName.substring(0, Math.max(0, fullName.lastIndexOf('.')))
31 |
32 | /** Returns the suffix of the action method invocation. Hence, a valid suffix is either a
33 | * package, class or method name.
34 | *
35 | * @note If present, the leading '@' is removed.
36 | */
37 | def suffix: String = fullName.substring(fullName.lastIndexOf('.') + 1)
38 |
39 | override def toString: String = input
40 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/routeeditor/handlers/Format.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.routeeditor.handlers
2 |
3 | import org.eclipse.core.commands.AbstractHandler
4 | import org.eclipse.core.commands.ExecutionEvent
5 | import org.eclipse.jface.text.ITextOperationTarget
6 | import org.eclipse.jface.text.source.ISourceViewer
7 | import org.eclipse.ui.handlers.HandlerUtil
8 | import org.scalaide.play2.routeeditor.RouteEditor
9 |
10 | /**
11 | * Invoke the formatter on a Route editor
12 | */
13 | class Format extends AbstractHandler {
14 | override def execute(event: ExecutionEvent): AnyRef = {
15 | HandlerUtil.getActiveEditor(event) match {
16 | case editor: RouteEditor =>
17 | // in our case, the viewer is always an ITexOperationTarget
18 | editor.getViewer.asInstanceOf[ITextOperationTarget].doOperation(ISourceViewer.FORMAT)
19 | }
20 | null
21 | }
22 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/routeeditor/hyperlink/MethodFinder.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.routeeditor.hyperlink
2 |
3 | import org.eclipse.jdt.core.IJavaElement
4 | import org.eclipse.jdt.core.search.IJavaSearchConstants
5 | import org.eclipse.jdt.core.search.IJavaSearchScope
6 | import org.eclipse.jdt.core.search.SearchPattern
7 | import org.eclipse.jdt.internal.core.search.BasicSearchEngine
8 | import scala.Array.apply
9 | import org.eclipse.core.runtime.NullProgressMonitor
10 | import org.eclipse.jdt.core.IJavaProject
11 |
12 | /**
13 | * Find Java methods in a given project.
14 | */
15 | class MethodFinder(project: IJavaProject) {
16 | /**
17 | * Returns an array of method elements which matches with the
18 | * criterion.
19 | *
20 | * @param methodName the name of method which we'd like to find
21 | * @param parameterTypes array of type of parameter of desired method
22 | * @return array of method element which matches the search
23 | */
24 | def searchMethod(methodName: String, parameterTypes: Array[String]): Array[IJavaElement] = {
25 | val stringPattern = methodName + getParametersString(parameterTypes)
26 | val methodPattern = SearchPattern.createPattern(stringPattern, IJavaSearchConstants.METHOD, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_PATTERN_MATCH)
27 | searchMethod(methodPattern)
28 | }
29 |
30 | private def searchMethod(methodPattern: SearchPattern): Array[IJavaElement] = {
31 | val requestor = doSearch(methodPattern)
32 | requestor.matchedElements.toArray
33 | }
34 |
35 | private def doSearch(pattern: SearchPattern): MethodSearchRequestor = {
36 | val participants = Array(BasicSearchEngine.getDefaultSearchParticipant)
37 | val scope = createJavaSearchScope()
38 | val requestor = new MethodSearchRequestor
39 | new BasicSearchEngine().search(pattern, participants, scope, requestor, new NullProgressMonitor)
40 | requestor
41 | }
42 |
43 | private[hyperlink] def getParametersString(parameterTypes: Array[String]) = {
44 | parameterTypes.mkString("(", ",", ")")
45 | }
46 |
47 | private def createJavaSearchScope(): IJavaSearchScope = {
48 | BasicSearchEngine.createJavaSearchScope(Array(project))
49 | }
50 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/routeeditor/hyperlink/MethodSearchRequestor.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.routeeditor.hyperlink
2 |
3 | import scala.collection.mutable
4 | import org.eclipse.jdt.core.IJavaElement
5 | import org.eclipse.jdt.core.search.SearchMatch
6 | import org.eclipse.jdt.core.search.SearchRequestor
7 | /**
8 | * contains the result of method search
9 | */
10 | class MethodSearchRequestor extends SearchRequestor {
11 | val matchedElements = new mutable.ListBuffer[IJavaElement]
12 | override def acceptSearchMatch(searchMatch: SearchMatch) = {
13 | val element = searchMatch.getElement
14 | matchedElements += element.asInstanceOf[IJavaElement]
15 | }
16 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/routeeditor/hyperlink/RouteHyperlinkDetector.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.routeeditor.hyperlink
2 |
3 | import org.eclipse.jdt.core.IJavaElement
4 | import org.eclipse.jdt.internal.ui.javaeditor.JavaElementHyperlink
5 | import org.eclipse.jdt.ui.actions.OpenAction
6 | import org.eclipse.jface.text.IRegion
7 | import org.eclipse.jface.text.ITextViewer
8 | import org.eclipse.jface.text.hyperlink.IHyperlink
9 | import org.eclipse.jface.text.hyperlink.IHyperlinkDetector
10 | import org.scalaide.play2.routeeditor.RouteAction
11 | import org.scalaide.play2.routeeditor.RouteEditor
12 |
13 | class RouteHyperlinkDetector(routeEditor: RouteEditor) extends IHyperlinkDetector {
14 | override def detectHyperlinks(textViewer: ITextViewer, region: IRegion, canShowMultipleHyperlinks: Boolean): Array[IHyperlink] = {
15 | routeEditor.getScalaProject.flatMap {
16 | scalaProject =>
17 | RouteHyperlinkComputer.detectHyperlinks(scalaProject, textViewer.getDocument(), region, createJavaHyperlink)
18 | }.map(Array(_)).getOrElse(null)
19 | }
20 |
21 | protected def createJavaHyperlink(routeAction: RouteAction, method: IJavaElement): IHyperlink = {
22 | val openAction = new OpenAction(
23 | routeEditor.getEditorSite())
24 | new JavaElementHyperlink(routeAction.region,
25 | openAction, method, false)
26 | }
27 |
28 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/routeeditor/lexical/AbstractRouteScanner.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.routeeditor.lexical
2 |
3 | import org.scalaide.core.lexical.AbstractScalaScanner
4 | import org.scalaide.ui.syntax.ScalaSyntaxClass
5 |
6 | import org.eclipse.jface.preference.IPreferenceStore
7 | import org.eclipse.jface.text.rules.RuleBasedScanner
8 |
9 | abstract class AbstractRouteScanner(defaultSyntax: ScalaSyntaxClass, prefStore: IPreferenceStore) extends RuleBasedScanner with AbstractScalaScanner {
10 | fDefaultReturnToken = getToken(defaultSyntax)
11 | override def preferenceStore = prefStore
12 |
13 | def getDefaultReturnToken = fDefaultReturnToken
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/routeeditor/lexical/HTTPKeywords.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.routeeditor.lexical
2 |
3 | object HTTPKeywords {
4 | final val Methods = Array("GET", "POST", "PUT", "PATCH", "HEAD", "DELETE", "OPTIONS").sorted
5 | }
6 |
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/routeeditor/lexical/MethodPackageRule.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.routeeditor.lexical
2 |
3 | import org.eclipse.jface.text.rules.ICharacterScanner
4 | import org.eclipse.jface.text.rules.IRule
5 | import org.eclipse.jface.text.rules.IToken
6 | import org.eclipse.jface.text.rules.Token
7 | /**
8 | * A rule for identifying a method name or package name
9 | */
10 | class MethodPackageRule(packageToken: IToken, methodToken: IToken) extends IRule {
11 | sealed class PackageReadingState(i: Int)
12 | case object Middle extends PackageReadingState(0)
13 | case object NotFound extends PackageReadingState(2)
14 | case object PackageFound extends PackageReadingState(3)
15 | case object MethodFound extends PackageReadingState(4)
16 |
17 | override def evaluate(scanner: ICharacterScanner) = {
18 | var state: PackageReadingState = NotFound
19 | var r = scanner.read()
20 | var c = r.asInstanceOf[Char]
21 | var rCount = 1
22 | if (r != ICharacterScanner.EOF && Character.isLowerCase(c)) {
23 | state = Middle
24 | while (state == Middle) {
25 | r = scanner.read();
26 | rCount += 1;
27 | c = r.asInstanceOf[Char];
28 | if (r == ICharacterScanner.EOF) {
29 | state = MethodFound
30 | }
31 | if (c == '.')
32 | state = PackageFound // `.' IS inside package token
33 | else if (c == '(') {
34 | state = MethodFound
35 | scanner.unread() // `(' is NOT inside method token
36 | }
37 | }
38 | }
39 | state match {
40 | case NotFound =>
41 | for (i <- 0 until rCount) {
42 | scanner.unread()
43 | }
44 | Token.UNDEFINED
45 | case PackageFound =>
46 | packageToken
47 | case MethodFound =>
48 | methodToken
49 | case _ =>
50 | Token.UNDEFINED // impossible to reach!
51 | }
52 | }
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/routeeditor/lexical/RouteActionScanner.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.routeeditor.lexical
2 |
3 | import org.eclipse.jdt.ui.text.IColorManager
4 | import org.eclipse.jface.preference.IPreferenceStore
5 | import org.eclipse.jface.text.rules.IRule
6 | import org.eclipse.jface.text.rules.IWordDetector
7 | import org.eclipse.jface.text.rules.WordRule
8 | import org.scalaide.play2.routeeditor.RouteSyntaxClasses.ACTION
9 | import org.scalaide.play2.routeeditor.RouteSyntaxClasses.ACTION_CLASS
10 | import org.scalaide.play2.routeeditor.RouteSyntaxClasses.ACTION_METHOD
11 | import org.scalaide.play2.routeeditor.RouteSyntaxClasses.ACTION_PACKAGE
12 | /**
13 | * scanner for action part of route file
14 | */
15 | class RouteActionScanner(prefStore: IPreferenceStore) extends AbstractRouteScanner(ACTION, prefStore) {
16 |
17 | val packageToken = getToken(ACTION_PACKAGE);
18 | val classToken = getToken(ACTION_CLASS);
19 | val methodToken = getToken(ACTION_METHOD);
20 | val methodArgumentToken = fDefaultReturnToken
21 |
22 | val rules = Array[IRule](
23 | // Add a rule for method argument
24 | new WordRule(new MethodArgumentDetector(),
25 | methodArgumentToken),
26 | // Add a rule for class
27 | new WordRule(new ClassDetector(), classToken),
28 | // Add a rule for method and package
29 | new MethodPackageRule(packageToken, methodToken))
30 |
31 | setRules(rules);
32 |
33 | private class ClassDetector extends IWordDetector {
34 |
35 | override def isWordStart(c: Char) = {
36 | Character.isUpperCase(c)
37 | }
38 |
39 | override def isWordPart(c: Char) = {
40 | Character.isJavaIdentifierPart(c);
41 | }
42 |
43 | }
44 |
45 | private class MethodArgumentDetector extends IWordDetector {
46 |
47 | override def isWordStart(c: Char) = {
48 | c == '('
49 | }
50 |
51 | override def isWordPart(c: Char) = {
52 | true
53 | }
54 |
55 | }
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/routeeditor/lexical/RouteDocumentPartitioner.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.routeeditor.lexical
2 |
3 | import org.eclipse.jface.text.TypedRegion
4 |
5 | import org.scalaide.play2.lexical.PlayDocumentPartitioner
6 |
7 | import RoutePartitions.ROUTE_DEFAULT
8 | import RoutePartitions.ROUTE_URI
9 |
10 | class RouteDocumentPartitioner(conservative: Boolean = false) extends PlayDocumentPartitioner(new RoutePartitionTokeniser, ROUTE_DEFAULT, conservative) {
11 |
12 | override def getLegalContentTypes: Array[String] = RoutePartitions.getTypes
13 |
14 | def uriPartitions: List[TypedRegion] = partitionRegions.filter(_.getType == ROUTE_URI)
15 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/routeeditor/lexical/RoutePartitions.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.routeeditor.lexical
2 |
3 | import org.eclipse.jface.text.IDocument
4 |
5 | object RoutePartitions {
6 | val ROUTE_PARTITIONING = "___route_partitioning"
7 | val ROUTE_URI = "__route_uri"
8 | val ROUTE_ACTION = "__route_action"
9 | val ROUTE_COMMENT = "__route_comment"
10 | val ROUTE_HTTP = "__route_http"
11 | val ROUTE_DEFAULT = IDocument.DEFAULT_CONTENT_TYPE
12 |
13 | val getTypes: Array[String] =
14 | Array(ROUTE_URI, ROUTE_ACTION, ROUTE_COMMENT, ROUTE_HTTP, ROUTE_DEFAULT);
15 |
16 | def isRouteAction(typeString: String): Boolean = typeString == ROUTE_ACTION
17 | }
18 |
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/routeeditor/lexical/RouteURIScanner.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.routeeditor.lexical
2 |
3 | import org.eclipse.jdt.ui.text.IColorManager
4 | import org.eclipse.jface.preference.IPreferenceStore
5 | import org.eclipse.jface.text.rules.IRule
6 | import org.eclipse.jface.text.rules.IWordDetector
7 | import org.eclipse.jface.text.rules.WordRule
8 | import org.scalaide.play2.routeeditor.RouteSyntaxClasses.URI
9 | import org.scalaide.play2.routeeditor.RouteSyntaxClasses.URI_DYNAMIC
10 | /**
11 | * scanner for URI part of route file
12 | */
13 | class RouteURIScanner(prefStore: IPreferenceStore) extends AbstractRouteScanner(URI, prefStore) {
14 | def dynamic = getToken(URI_DYNAMIC)
15 |
16 | val rules = Array[IRule](
17 | // Add a rule for dynamic with colon
18 | new WordRule(new DynamicColonDetector(), dynamic),
19 | // Add a rule for dynamic with star
20 | new WordRule(new DynamicStarDetector(), dynamic),
21 | // Add a rule for dynamic with dollar
22 | new WordRule(new DynamicDollarDetector(), dynamic),
23 | // Add a rule for static
24 | new WordRule(new StaticDetector(), fDefaultReturnToken))
25 | setRules(rules);
26 |
27 | private class StaticDetector extends IWordDetector {
28 | override def isWordStart(c: Char) = {
29 | c == '/'
30 | }
31 |
32 | override def isWordPart(c: Char): Boolean = {
33 | for (w <- " \t\n") {
34 | if (c == w)
35 | return false;
36 | }
37 | return !(c == ':' || c == '*' || c == '$')
38 | }
39 |
40 | }
41 |
42 | private abstract class DynamicDetector(start: Char, whiteSpaces: Array[Char]) extends IWordDetector {
43 | def this(start: Char, whiteSpaces: String) = {
44 | this(start, whiteSpaces.toCharArray);
45 | }
46 |
47 | override def isWordStart(c: Char) = {
48 | c == start
49 | }
50 |
51 | override def isWordPart(c: Char): Boolean = {
52 | for (w <- whiteSpaces) {
53 | if (c == w)
54 | return false;
55 | }
56 | return true;
57 | }
58 |
59 | }
60 |
61 | private class DynamicColonDetector extends DynamicDetector(':', " \t\n")
62 |
63 | private class DynamicStarDetector extends DynamicDetector('*', " \t\n")
64 |
65 | private class DynamicDollarDetector extends DynamicDetector('$', " \t\n")
66 | }
67 |
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/routeeditor/properties/RouteColorPreferenceInitializer.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.routeeditor.properties
2 | import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer
3 | import org.eclipse.jface.preference.IPreferenceStore
4 | import org.eclipse.jface.resource.StringConverter
5 | import org.eclipse.swt.graphics.RGB
6 | import org.scalaide.ui.syntax.ScalaSyntaxClass
7 | import org.scalaide.play2.PlayPlugin
8 | import org.scalaide.play2.routeeditor.RouteSyntaxClasses._
9 |
10 | class RouteColorPreferenceInitializer extends AbstractPreferenceInitializer {
11 |
12 | override def initializeDefaultPreferences() {
13 | doInitializeDefaultPreferences()
14 | }
15 |
16 | private def doInitializeDefaultPreferences() {
17 | val prefStore = PlayPlugin.preferenceStore
18 | setDefaultsForSyntaxClasses(prefStore)
19 | prefStore.setDefault(PlayPlugin.RouteFormatterMarginId, 3) // for formatter
20 | }
21 |
22 | private def setDefaultsForSyntaxClass(
23 | syntaxClass: ScalaSyntaxClass,
24 | foregroundRGB: RGB,
25 | enabled: Boolean = true,
26 | backgroundRGBOpt: Option[RGB] = None,
27 | bold: Boolean = false,
28 | italic: Boolean = false,
29 | strikethrough: Boolean = false,
30 | underline: Boolean = false)(implicit scalaPrefStore: IPreferenceStore) =
31 | {
32 | lazy val WHITE = new RGB(255, 255, 255)
33 | scalaPrefStore.setDefault(syntaxClass.enabledKey, enabled)
34 | scalaPrefStore.setDefault(syntaxClass.foregroundColorKey, StringConverter.asString(foregroundRGB))
35 | val defaultBackgroundColor = StringConverter.asString(backgroundRGBOpt getOrElse WHITE)
36 | scalaPrefStore.setDefault(syntaxClass.backgroundColorKey, defaultBackgroundColor)
37 | scalaPrefStore.setDefault(syntaxClass.backgroundColorEnabledKey, backgroundRGBOpt.isDefined)
38 | scalaPrefStore.setDefault(syntaxClass.boldKey, bold)
39 | scalaPrefStore.setDefault(syntaxClass.italicKey, italic)
40 | scalaPrefStore.setDefault(syntaxClass.underlineKey, underline)
41 | }
42 |
43 | private def setDefaultsForSyntaxClasses(implicit scalaPrefStore: IPreferenceStore) {
44 | setDefaultsForSyntaxClass(COMMENT, new RGB(128, 128, 0))
45 | setDefaultsForSyntaxClass(URI, new RGB(0, 0, 128))
46 | setDefaultsForSyntaxClass(URI_DYNAMIC, new RGB(128, 128, 255))
47 | setDefaultsForSyntaxClass(ACTION, new RGB(128, 0, 0))
48 | setDefaultsForSyntaxClass(ACTION_PACKAGE, new RGB(196, 196, 196))
49 | setDefaultsForSyntaxClass(ACTION_CLASS, new RGB(63, 46, 255))
50 | setDefaultsForSyntaxClass(ACTION_METHOD, new RGB(0, 0, 0), italic = true)
51 | setDefaultsForSyntaxClass(DEFAULT, new RGB(0, 0, 0))
52 | setDefaultsForSyntaxClass(HTTP_KEYWORD, new RGB(139, 10, 80), bold = true)
53 | }
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/routeeditor/properties/RouteFormatterPreferencePage.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.routeeditor.properties
2 |
3 | import org.eclipse.jface.preference.FieldEditorPreferencePage
4 | import org.eclipse.jface.preference.IntegerFieldEditor
5 | import org.eclipse.ui.IWorkbench
6 | import org.eclipse.ui.IWorkbenchPreferencePage
7 | import org.scalaide.play2.PlayPlugin
8 |
9 | class RouteFormatterPreferencePage extends FieldEditorPreferencePage with IWorkbenchPreferencePage {
10 |
11 | setPreferenceStore(PlayPlugin.preferenceStore)
12 |
13 | override def createFieldEditors() {
14 | val marginField = new IntegerFieldEditor(PlayPlugin.RouteFormatterMarginId, "Number of spaces between columns", getFieldEditorParent)
15 | marginField.setValidRange(1, 10)
16 | addField(marginField)
17 |
18 | val formatOnSaveToggle = new org.eclipse.jface.preference.BooleanFieldEditor(PlayPlugin.RouteFormatterFormatOnSaveId, "Format on save", getFieldEditorParent)
19 | addField(formatOnSaveToggle);
20 | }
21 |
22 | def init(workbench: IWorkbench) {}
23 |
24 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/routeeditor/properties/RoutePreviewerFactoryConfiguration.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.routeeditor.properties
2 |
3 | import org.eclipse.jface.preference.IPreferenceStore
4 | import org.scalaide.ui.syntax.preferences.PreviewerFactoryConfiguration
5 | import org.scalaide.play2.routeeditor.RouteConfiguration
6 | import org.scalaide.play2.routeeditor.lexical.RouteDocumentPartitioner
7 | import java.util.HashMap
8 | import org.eclipse.jface.text.IDocumentPartitioner
9 | import org.scalaide.play2.routeeditor.lexical.RoutePartitions
10 | import org.eclipse.jface.text.IDocumentExtension3
11 |
12 | object RoutePreviewerFactoryConfiguration extends PreviewerFactoryConfiguration {
13 |
14 | def getConfiguration(preferenceStore: IPreferenceStore) =
15 | new RouteConfiguration(preferenceStore, null)
16 |
17 | def getDocumentPartitioners(): Map[String, IDocumentPartitioner] =
18 | Map((IDocumentExtension3.DEFAULT_PARTITIONING, new RouteDocumentPartitioner(true)))
19 |
20 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/routeeditor/properties/RouteSyntaxColoringPreferencePage.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.routeeditor.properties
2 |
3 | import org.scalaide.play2.routeeditor.RouteSyntaxClasses
4 | import org.scalaide.ui.syntax.preferences.BaseSyntaxColoringPreferencePage
5 | import org.scalaide.play2.PlayPlugin
6 |
7 | class RouteSyntaxColoringPreferencePage extends BaseSyntaxColoringPreferencePage(
8 | RouteSyntaxClasses.categories,
9 | RouteSyntaxClasses.routeOtherCategory,
10 | PlayPlugin.instance().getPreferenceStore,
11 | RouteSyntaxColoringPreferencePage.previewText,
12 | RoutePreviewerFactoryConfiguration)
13 |
14 | object RouteSyntaxColoringPreferencePage {
15 | val previewText =
16 | """#Route file
17 | |GET /static_part/:dynamic_part package1.package2.Class1.method(stringParameter, intParameter)
18 | |""".stripMargin
19 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/templateeditor/BracketAutoEditStrategy.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.templateeditor
2 |
3 | import org.eclipse.jface.preference.IPreferenceStore
4 | import org.eclipse.jface.text.DocumentCommand
5 | import org.eclipse.jface.text.IAutoEditStrategy
6 | import org.eclipse.jface.text.IDocument
7 |
8 | /**
9 | * Copied from scala-ide.core since the class has been removed.
10 | */
11 | class BracketAutoEditStrategy(prefStore: IPreferenceStore) extends IAutoEditStrategy {
12 |
13 | def customizeDocumentCommand(document: IDocument, command: DocumentCommand) = {
14 | def ch(i: Int, c: Char) = {
15 | val o = command.offset + i
16 | o >= 0 && o < document.getLength && document.getChar(o) == c
17 | }
18 |
19 | def jumpOverClosingBrace() = {
20 | if (ch(0, '}')) {
21 | command.text = ""
22 | command.caretOffset = command.offset + 1
23 | }
24 | }
25 |
26 | def removeClosingBrace() = {
27 | if (ch(0, '{') && ch(1, '}')) {
28 | command.length = 2
29 | }
30 | }
31 |
32 | command.text match {
33 | case "}" => jumpOverClosingBrace()
34 | case "" => removeClosingBrace()
35 | case _ =>
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/templateeditor/TemplateDocumentProvider.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.templateeditor
2 |
3 | import org.eclipse.jface.text.IDocument
4 | import org.eclipse.ui.editors.text.FileDocumentProvider
5 | import org.scalaide.play2.templateeditor.lexical.TemplateDocumentPartitioner
6 |
7 | class TemplateDocumentProvider extends FileDocumentProvider/* with IAnnotationModelFactory */{
8 | protected override def createDocument(element: Object): IDocument = {
9 | val document = super.createDocument(element);
10 | if (document != null) {
11 | val partitioner = new TemplateDocumentPartitioner(true)
12 | partitioner.connect(document)
13 | document.setDocumentPartitioner(partitioner)
14 | }
15 | document
16 | }
17 |
18 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/templateeditor/TemplateEditor.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.templateeditor
2 |
3 | import scala.collection.JavaConverters
4 | import org.eclipse.jdt.core.compiler.IProblem
5 | import org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitDocumentProvider.ProblemAnnotation
6 | import org.eclipse.jface.text.Position
7 | import org.eclipse.jface.text.source.IAnnotationModel
8 | import org.eclipse.jface.text.source.IAnnotationModelExtension
9 | import org.eclipse.jface.text.source.IAnnotationModelExtension2
10 | import org.eclipse.jface.text.source.ISourceViewer
11 | import org.eclipse.jface.util.PropertyChangeEvent
12 | import org.eclipse.ui.editors.text.EditorsUI
13 | import org.eclipse.ui.texteditor.ChainedPreferenceStore
14 | import org.scalaide.play2.PlayPlugin
15 | import org.scalaide.ui.editor.SourceCodeEditor
16 | import org.scalaide.ui.editor.CompilationUnitProvider
17 | import org.eclipse.jface.preference.IPreferenceStore
18 | import org.eclipse.ui.editors.text.TextEditor
19 | import org.eclipse.jface.text.source.IVerticalRuler
20 | import org.eclipse.swt.widgets.Composite
21 | import org.scalaide.play2.util.StoredEditorUtils
22 |
23 | trait AbstractTemplateEditor extends SourceCodeEditor { self: TextEditor =>
24 |
25 | override protected type UnderlyingCompilationUnit = TemplateCompilationUnit
26 |
27 | override val compilationUnitProvider: CompilationUnitProvider[UnderlyingCompilationUnit] = new TemplateCompilationUnitProvider(false)
28 | }
29 |
30 | class TemplateEditor extends TextEditor with AbstractTemplateEditor {
31 |
32 | override protected lazy val preferenceStore: IPreferenceStore = new ChainedPreferenceStore(Array((EditorsUI.getPreferenceStore()), PlayPlugin.preferenceStore))
33 | private val sourceViewConfiguration = new TemplateConfiguration(preferenceStore, this)
34 | private val documentProvider = new TemplateDocumentProvider()
35 |
36 | setSourceViewerConfiguration(sourceViewConfiguration);
37 | setPreferenceStore(preferenceStore)
38 | setDocumentProvider(documentProvider);
39 |
40 | override def handlePreferenceStoreChanged(event: PropertyChangeEvent) = {
41 | sourceViewConfiguration.propertyChange(event)
42 | super.handlePreferenceStoreChanged(event)
43 | }
44 |
45 | override def affectsTextPresentation(event: PropertyChangeEvent): Boolean = {
46 | // TODO: more precise filtering
47 | true
48 | }
49 |
50 | override def editorSaved() = {
51 | super.editorSaved()
52 | sourceViewConfiguration.strategy.reconcile(null)
53 | }
54 | override def createSourceViewer(parent: Composite, verticalRuler: IVerticalRuler, styles: Int): ISourceViewer = {
55 | val sourceViewer = super.createSourceViewer(parent, verticalRuler, styles)
56 | StoredEditorUtils.storeEditorInViewer(sourceViewer, this)
57 | sourceViewer
58 | }
59 | }
60 |
61 | object TemplateEditor {
62 | /** The annotation types shown when hovering on the left-side ruler (or in the status bar). */
63 | val annotationsShownInHover = Set(
64 | "org.eclipse.jdt.ui.error", "org.eclipse.jdt.ui.warning", "org.eclipse.jdt.ui.info")
65 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/templateeditor/TemplateSyntaxClasses.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.templateeditor
2 |
3 | import org.scalaide.ui.syntax.ScalaSyntaxClass
4 | import org.scalaide.ui.syntax.ScalaSyntaxClass.Category
5 | import org.scalaide.ui.syntax.ScalaSyntaxClasses
6 |
7 | object TemplateSyntaxClasses {
8 | val DEFAULT = ScalaSyntaxClass("Default", "template.default")
9 | val PLAIN = ScalaSyntaxClass("Plain", "template.plain")
10 | val COMMENT = ScalaSyntaxClass("Template Comment", "template.comment")
11 | val MAGIC_AT = ScalaSyntaxClass("Template Magic @", "template.at")
12 | val BRACE = ScalaSyntaxClass("Template Brace", "template.brace")
13 |
14 | val scalaCategory = Category("Scala", List(ScalaSyntaxClasses.KEYWORD,
15 | ScalaSyntaxClasses.STRING,
16 | ScalaSyntaxClasses.DEFAULT,
17 | ScalaSyntaxClasses.OPERATOR,
18 | ScalaSyntaxClasses.BRACKET,
19 | ScalaSyntaxClasses.RETURN,
20 | ScalaSyntaxClasses.SYMBOL,
21 | ScalaSyntaxClasses.MULTI_LINE_STRING,
22 | ScalaSyntaxClasses.NUMBER_LITERAL))
23 |
24 | val htmlCategory = Category("HTML", List(ScalaSyntaxClasses.XML_COMMENT,
25 | ScalaSyntaxClasses.XML_ATTRIBUTE_VALUE,
26 | ScalaSyntaxClasses.XML_ATTRIBUTE_NAME,
27 | ScalaSyntaxClasses.XML_ATTRIBUTE_EQUALS,
28 | ScalaSyntaxClasses.XML_TAG_DELIMITER,
29 | ScalaSyntaxClasses.XML_TAG_NAME,
30 | ScalaSyntaxClasses.XML_PI,
31 | ScalaSyntaxClasses.XML_CDATA_BORDER))
32 |
33 | val commentsCategory = Category("Comments", List(ScalaSyntaxClasses.SINGLE_LINE_COMMENT,
34 | ScalaSyntaxClasses.MULTI_LINE_COMMENT,
35 | ScalaSyntaxClasses.SCALADOC,
36 | COMMENT))
37 |
38 | val otherCategory = Category("Other", List(
39 | DEFAULT, PLAIN, MAGIC_AT, BRACE))
40 |
41 | val categories = List(scalaCategory, htmlCategory, commentsCategory, otherCategory)
42 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/templateeditor/compiler/CompilerUsing.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.templateeditor.compiler
2 |
3 | import java.io.File
4 |
5 | import scala.io.Codec
6 | import scala.util.Failure
7 | import scala.util.Try
8 |
9 | import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities
10 | import org.scalaide.core.compiler.ScalaCompilationProblem
11 | import org.scalaide.logging.HasLogger
12 | import org.scalaide.play2.PlayProject
13 | import org.scalaide.play2.properties.PlayPreferences.PlayVersion
14 | import org.scalaide.play2.templateeditor.processing.GeneratedSource
15 | import org.scalaide.play2.templateeditor.processing.TemplateProcessingProvider
16 |
17 | /**
18 | * a helper for using template compiler
19 | */
20 | object CompilerUsing extends HasLogger {
21 | /**
22 | * invokes compile method of template compiler and returns generated source object or
23 | * in the case of error, returns appropriate exception
24 | */
25 | def compileTemplateToScalaVirtual(content: String, source: File, playProject: PlayProject, inclusiveDot: Boolean): Try[GeneratedSource] = {
26 | val sourcePath = playProject.sourceDir.getAbsolutePath()
27 | if (source.getAbsolutePath().indexOf(sourcePath) == -1)
28 | logger.debug(s"Template file '${source.getAbsolutePath}' must be located in '$sourcePath' or one of its subfolders!")
29 |
30 | val extension = source.getName.split('.').last
31 |
32 | val playVersion = if (playProject.cachedPreferenceStore.getString(PlayVersion).isEmpty())
33 | None
34 | else
35 | Some(playProject.cachedPreferenceStore.getString(PlayVersion))
36 |
37 | TemplateProcessingProvider.templateProcessing(playVersion).compile(
38 | content,
39 | source,
40 | playProject.sourceDir,
41 | playProject.templateImports(extension),
42 | Codec.default,
43 | inclusiveDot).recoverWith {
44 | case ex: Exception => {
45 | val error = s"Caught unknown exception: '${ex.getMessage()}'\n${ex.getStackTraceString}"
46 | Failure(TemplateToScalaCompilationError(source, error, 0, 0, 0))
47 | }
48 | }
49 | }
50 |
51 | }
52 |
53 | case class TemplateToScalaCompilationError(source: File, message: String, offset: Int, line: Int, column: Int) extends RuntimeException(message) {
54 | override def toString = source.getName + ": " + message + offset + " " + line + "." + column
55 |
56 | import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities
57 |
58 | def toProblem: ScalaCompilationProblem =
59 | ScalaCompilationProblem(
60 | source.getAbsolutePath().toString,
61 | ProblemSeverities.Error,
62 | message,
63 | Math.max(offset - 1, 0),
64 | Math.max(offset - 1, 0),
65 | line,
66 | column)
67 | }
68 |
69 | object PositionHelper {
70 | def convertLineColumnToOffset(source: File, line: Int, column: Int): Int = {
71 | convertLineColumnToOffset(scala.io.Source.fromFile(source).mkString, line, column)
72 | }
73 |
74 | def convertLineColumnToOffset(content: String, line: Int, column: Int): Int = {
75 | // splitting the string will cause some problems
76 | var offset = 0
77 | for (i <- 1 until line) {
78 | offset = content.indexOf("\n", offset) + 1
79 | }
80 | offset += column - 1
81 | offset
82 | }
83 |
84 | def mapSourcePosition(matrix: Seq[(Int, Int)], sourcePosition: Int): Int = {
85 | val sortedMatrix = matrix.sortBy(_._2)
86 | sortedMatrix.indexWhere(p => p._2 > sourcePosition) match {
87 | case 0 => 0
88 | case i if i > 0 => {
89 | val pos = sortedMatrix(i - 1)
90 | pos._1 + (sourcePosition - pos._2)
91 | }
92 | case _ => {
93 | val pos = sortedMatrix.takeRight(1)(0)
94 | pos._1 + (sourcePosition - pos._2)
95 | }
96 | }
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/templateeditor/hyperlink/TemplateDeclarationHyperlinkDetector.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.templateeditor.hyperlink
2 |
3 | import org.eclipse.jdt.internal.ui.javaeditor.JavaEditor
4 | import org.eclipse.jdt.internal.ui.javaeditor.JavaElementHyperlink
5 | import org.eclipse.jdt.ui.actions.OpenAction
6 | import org.eclipse.jface.text.IRegion
7 | import org.eclipse.jface.text.hyperlink.AbstractHyperlinkDetector
8 | import org.eclipse.jface.text.hyperlink.IHyperlink
9 | import org.eclipse.ui.texteditor.ITextEditor
10 | import org.scalaide.util.ScalaWordFinder
11 | import org.scalaide.core.compiler.InteractiveCompilationUnit
12 | import org.eclipse.jdt.internal.core.JavaProject
13 | import org.eclipse.jdt.internal.core.DefaultWorkingCopyOwner
14 | import org.scalaide.play2.templateeditor.lexical.TemplatePartitions
15 | import org.eclipse.jface.text.Region
16 | import org.scalaide.play2.templateeditor.compiler.PositionHelper
17 | import org.scalaide.play2.templateeditor.TemplateCompilationUnit
18 | import org.scalaide.ui.editor.SourceConfiguration
19 |
20 |
21 | object TemplateDeclarationHyperlinkDetector {
22 | def apply()= SourceConfiguration.scalaDeclarationDetector
23 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/templateeditor/lexical/HtmlTagScanner.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.templateeditor.lexical
2 |
3 | import org.scalaide.core.internal.lexical.XmlTagScanner
4 | import org.eclipse.jdt.ui.text.IColorManager
5 | import org.eclipse.jface.preference.IPreferenceStore
6 | import org.eclipse.jface.text.IDocument
7 | import org.eclipse.jface.text.rules.IToken
8 | import org.scalaide.ui.syntax.ScalaSyntaxClasses._
9 |
10 | /** A special code scanner for Play templates. It only mark the beginning and end quotes as
11 | */
12 | class HtmlTagScanner(preferenceStore: IPreferenceStore) extends XmlTagScanner(preferenceStore) {
13 | import XmlTagScanner._
14 |
15 | var start: Int = -1
16 |
17 | override def setRange(document: IDocument, offset: Int, length: Int) {
18 | super.setRange(document, offset, length)
19 | this.start = offset
20 | }
21 |
22 | private def ch = if (pos > end) EOF else document.getChar(pos)
23 |
24 | override def nextToken(): IToken = {
25 | if (pos == start && pos != -1) {
26 | ch match {
27 | case '\'' | '\"' => {
28 | tokenOffset = start
29 | tokenLength = 1
30 | pos += 1
31 | return getToken(XML_ATTRIBUTE_VALUE)
32 | }
33 | case _ =>
34 | }
35 | }
36 | super.nextToken
37 | }
38 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/templateeditor/lexical/TemplateDefaultScanner.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.templateeditor.lexical
2 |
3 | import org.eclipse.jdt.ui.text.IColorManager
4 | import org.eclipse.jface.preference.IPreferenceStore
5 | import org.eclipse.jface.text.rules.IRule
6 | import org.eclipse.jface.text.rules.IWordDetector
7 | import org.eclipse.jface.text.rules.WordRule
8 | import org.scalaide.play2.routeeditor.lexical.AbstractRouteScanner
9 | import org.scalaide.play2.templateeditor.TemplateSyntaxClasses
10 |
11 | class TemplateDefaultScanner(prefStore: IPreferenceStore) extends AbstractRouteScanner(TemplateSyntaxClasses.DEFAULT, prefStore) {
12 | val atToken = getToken(TemplateSyntaxClasses.MAGIC_AT);
13 | val braceToken = getToken(TemplateSyntaxClasses.BRACE);
14 |
15 | val rules = Array[IRule](
16 | new WordRule(new OperatorDetector('@'),
17 | atToken),
18 | new WordRule(new OperatorDetector('{', '}'), braceToken))
19 |
20 | setRules(rules);
21 |
22 | private class OperatorDetector(operators: Char*) extends IWordDetector {
23 |
24 | override def isWordStart(c: Char) = {
25 | operators exists (_ == c)
26 | }
27 |
28 | override def isWordPart(c: Char) = {
29 | false
30 | }
31 |
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/templateeditor/lexical/TemplateDocumentPartitioner.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.templateeditor.lexical
2 |
3 | import org.scalaide.play2.lexical.PlayDocumentPartitioner
4 | import TemplatePartitions.TEMPLATE_COMMENT
5 | import TemplatePartitions.TEMPLATE_DEFAULT
6 | import TemplatePartitions.TEMPLATE_SCALA
7 | import org.eclipse.jface.text.ITypedRegion
8 |
9 | class TemplateDocumentPartitioner(conservative: Boolean = false) extends PlayDocumentPartitioner(new TemplatePartitionTokeniser, TemplatePartitions.TEMPLATE_DEFAULT, conservative) {
10 |
11 | import TemplateDocumentPartitioner._
12 |
13 | def getLegalContentTypes = LEGAL_CONTENT_TYPES
14 |
15 | override def getPartition(offset: Int, preferOpenPartitions: Boolean): ITypedRegion = {
16 | val region = super.getPartition(offset, preferOpenPartitions)
17 | if (preferOpenPartitions)
18 | if (region.getOffset == offset && region.getType != defaultPartition)
19 | if (offset > 0) {
20 | val previousRegion = getPartition(offset - 1)
21 | // FIXME: This doesn't make any sense to me. We should prioritize the previous
22 | // partition only if it's meaningful, i.e., if it is NOT the default partitioning.
23 | // Hence, I'm wondering if the template editor actually relies on this logic, as
24 | // it seems pretty useless and could actually cause some completion proposals to
25 | // no show up because the default partitioning (instead of a specific one) is returned.
26 | if (previousRegion.getType == defaultPartition)
27 | return previousRegion
28 | }
29 | region
30 | }
31 | }
32 |
33 | object TemplateDocumentPartitioner {
34 |
35 | private val LEGAL_CONTENT_TYPES = Array[String](
36 | TEMPLATE_DEFAULT, TEMPLATE_SCALA, TEMPLATE_COMMENT)
37 |
38 | val NO_PARTITION_AT_ALL = "__no_partition_at_all"
39 |
40 | final val EOF = '\u001A'
41 |
42 | }
43 |
44 |
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/templateeditor/lexical/TemplateParsing.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.templateeditor.lexical
2 |
3 | import scala.util.parsing.input.CharSequenceReader
4 | import scala.util.parsing.input.OffsetPosition
5 | import scala.util.parsing.input.Positional
6 |
7 | import org.scalaide.play2.templateeditor.processing.TemplateProcessingProvider
8 |
9 | /**
10 | * A helper for using template parser
11 | */
12 | object TemplateParsing {
13 | implicit def stringToCharSeq(str: String) = new CharSequenceReader(str)
14 |
15 | sealed abstract class PlayTemplate(input: Positional, kind: String) {
16 | val offset = input.pos match {
17 | case offsetPosition: OffsetPosition =>
18 | offsetPosition.offset
19 | case _ =>
20 | -1
21 | }
22 | val length = TemplateProcessingProvider.templateProcessing().length(input)
23 |
24 | override def toString = kind + "[" + offset + " - " + length + "]: " + input
25 | }
26 | case class ScalaCode(input: Positional) extends PlayTemplate(input, "sc")
27 | case class DefaultCode(input: Positional) extends PlayTemplate(input, "df")
28 | case class CommentCode(input: Positional) extends PlayTemplate(input, "cm")
29 |
30 | /**
31 | * Returns list of different types of region of the template code
32 | */
33 | def handleTemplateCode(templateCode: String) =
34 | TemplateProcessingProvider.templateProcessing().parse(templateCode)
35 | }
36 |
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/templateeditor/lexical/TemplatePartitions.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.templateeditor.lexical
2 |
3 | import org.eclipse.jface.text.IDocument
4 |
5 |
6 | object TemplatePartitions {
7 | val TEMPLATE_PARTITIONING = "___template_partitioning";
8 | val TEMPLATE_DEFAULT = IDocument.DEFAULT_CONTENT_TYPE
9 | val TEMPLATE_SCALA = "__template_scala"
10 | val TEMPLATE_COMMENT = "__template_comment"
11 | val TEMPLATE_PLAIN = "__template_plain"
12 | val TEMPLATE_TAG = "__template_tag"
13 |
14 | def getTypes() = {
15 | Array(TEMPLATE_DEFAULT, TEMPLATE_SCALA, TEMPLATE_COMMENT, TEMPLATE_TAG, TEMPLATE_PLAIN);
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/templateeditor/processing/TemplateProcessing.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.templateeditor.processing
2 |
3 | import java.io.File
4 |
5 | import scala.io.Codec
6 | import scala.util.Try
7 | import scala.util.parsing.input.Positional
8 |
9 | import org.scalaide.play2.templateeditor.lexical.TemplateParsing.PlayTemplate
10 |
11 | /**
12 | * Thought as the interface to template parser and compiler as long as Twirl library does not define
13 | * the abstraction for these two functionalities. Implemented by extensions of [[TemplateProcessingProvider.ExtensionPointId]]
14 | */
15 | trait TemplateProcessing {
16 | /**
17 | * Parses and returns list of different types of region of the template code.
18 | * @param templateCode template code to parse
19 | * @return a list of [[PlayTemplate]] objects
20 | */
21 | def parse(templateCode: String): List[PlayTemplate]
22 |
23 | /**
24 | * Gets length of parsed token.
25 | * @param token as [[Positional]]
26 | * @return length of token
27 | */
28 | def length(input: Positional): Int
29 |
30 | /**
31 | * Invokes compile method of template compiler and returns generated source object or
32 | * in the case of error, returns appropriate exception.
33 | * @param content with template code
34 | * @param source keeps the template file
35 | * @param sourceDirectory
36 | * @param additionalImports
37 | * @param codec to decode charset used in template
38 | * @param inclusiveDot
39 | * @return generated scala source
40 | */
41 | def compile(content: String, source: File, sourceDirectory: File, additionalImports: String, codec: Codec, inclusiveDot: Boolean): Try[GeneratedSource]
42 | }
43 |
44 | trait GeneratedSource {
45 | def content: String
46 | def matrix: Seq[(Int, Int)]
47 | def mapPosition(generatedPosition: Int): Int
48 | }
49 |
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/templateeditor/processing/TemplateProcessingProvider.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.templateeditor.processing
2 |
3 | import org.eclipse.core.runtime.RegistryFactory
4 | import org.scalaide.logging.HasLogger
5 | import org.scalaide.play2.properties.PlayPreferences
6 |
7 | object TemplateProcessingProvider extends HasLogger {
8 | val ExtensionPointId = "org.scalaide.play2.template.processing"
9 |
10 | def templateProcessing(templateVersion: Option[String] = None): TemplateProcessing = {
11 | val extensions = RegistryFactory.getRegistry.getConfigurationElementsFor(ExtensionPointId)
12 | val playVersion = templateVersion.orElse(TemplateVersionExhibitor.get.flatMap { version =>
13 | if (version.isEmpty) None else Some(version)
14 | }).orElse {
15 | eclipseLog.warn(s"Cannot find template version. Dropped to default ${PlayPreferences.DefaultPlayVersion}.")
16 | Some(PlayPreferences.DefaultPlayVersion)
17 | }
18 | val version = playVersion.flatMap { pVer =>
19 | extensions.find {
20 | _.getChildren("version").map {
21 | _.getAttribute("supports")
22 | }.contains(pVer)
23 | }
24 | }
25 | if (version.nonEmpty)
26 | version.get.createExecutableExtension("class").asInstanceOf[TemplateProcessing]
27 | else
28 | throw new IllegalStateException(s"Cannot find template processing for Play version: ${playVersion.getOrElse("version not found")}.")
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/templateeditor/processing/TemplateVersionExhibitor.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.templateeditor.processing
2 |
3 | object TemplateVersionExhibitor {
4 | private val templateVersionStock: ThreadLocal[Option[String]] =
5 | new ThreadLocal[Option[String]] {
6 | override protected def initialValue: Option[String] = None
7 | }
8 |
9 | def get: Option[String] = templateVersionStock.get
10 |
11 | def set(templateVersion: Option[String]): Unit = templateVersionStock.set(templateVersion)
12 |
13 | def clean(): Unit = templateVersionStock.remove()
14 | }
15 |
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/templateeditor/processing/TemplateVersionExtractor.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.templateeditor.processing
2 |
3 | import org.eclipse.core.resources.IFile
4 | import org.scalaide.play2.PlayPlugin
5 | import org.scalaide.play2.properties.PlayPreferences
6 |
7 | object TemplateVersionExtractor {
8 | def fromIFile(resource: IFile): Option[String] =
9 | PlayPlugin.instance().asPlayProject(resource.getProject).flatMap { project =>
10 | val templateVersion = project.cachedPreferenceStore.getString(PlayPreferences.PlayVersion)
11 | if (templateVersion.isEmpty())
12 | None
13 | else
14 | Some(templateVersion)
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/templateeditor/properties/TemplatePreviewerFactoryConfiguration.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.templateeditor.properties
2 |
3 | import org.eclipse.jface.preference.IPreferenceStore
4 | import org.scalaide.play2.templateeditor.TemplateConfiguration
5 | import org.scalaide.play2.templateeditor.lexical.TemplateDocumentPartitioner
6 | import org.scalaide.ui.syntax.preferences.PreviewerFactoryConfiguration
7 | import org.scalaide.play2.templateeditor.lexical.TemplatePartitions
8 | import java.util.HashMap
9 | import org.eclipse.jface.text.IDocumentPartitioner
10 | import org.eclipse.jface.text.IDocumentExtension3
11 |
12 | object TemplatePreviewerFactoryConfiguration extends PreviewerFactoryConfiguration {
13 |
14 | def getConfiguration(preferenceStore: IPreferenceStore) =
15 | new TemplateConfiguration(preferenceStore, null)
16 |
17 | def getDocumentPartitioners(): Map[String, IDocumentPartitioner] =
18 | Map((IDocumentExtension3.DEFAULT_PARTITIONING, new TemplateDocumentPartitioner(true)))
19 |
20 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/templateeditor/properties/TemplateSyntaxColoringPreferencePage.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.templateeditor.properties
2 |
3 | import org.scalaide.ui.syntax.preferences.BaseSyntaxColoringPreferencePage
4 | import org.scalaide.play2.templateeditor.TemplateSyntaxClasses
5 | import org.scalaide.play2.PlayPlugin
6 |
7 |
8 | class TemplateSyntaxColoringPreferencePage extends BaseSyntaxColoringPreferencePage(
9 | TemplateSyntaxClasses.categories,
10 | TemplateSyntaxClasses.scalaCategory,
11 | PlayPlugin.instance().getPreferenceStore,
12 | TemplateSyntaxColoringPreferencePage.previewText,
13 | TemplatePreviewerFactoryConfiguration)
14 |
15 |
16 |
17 | object TemplateSyntaxColoringPreferencePage {
18 |
19 | val previewText =
20 | """@* Template Comment *@
21 | |@(param: String, items: List[Item])
22 | |
23 | |@{
24 | | class A {
25 | | val b = "some string"
26 | | val n = 12.3
27 | | println("sym" + 'sym)
28 | | }
29 | |
30 | | new A
31 | |}
32 | |@items.foreach { item =>
33 | | @{return item}
34 | |}
35 | |
36 | |""".stripMargin
37 |
38 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/templateeditor/reconciler/TemplateReconcilingStrategy.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.templateeditor.reconciler
2 |
3 | import org.eclipse.jface.text.DocumentEvent
4 | import org.eclipse.jface.text.IDocumentListener
5 | import org.scalaide.ui.editor.ReconcilingStrategy
6 | import org.scalaide.ui.editor.SourceCodeEditor
7 | import org.scalaide.play2.templateeditor.AbstractTemplateEditor
8 |
9 | private class TemplateReconcilingStrategy(templateEditor: SourceCodeEditor, documentListener: IDocumentListener) extends ReconcilingStrategy(templateEditor, documentListener)
10 |
11 | object TemplateReconcilingStrategy {
12 |
13 | def apply(templateEditor: AbstractTemplateEditor): ReconcilingStrategy = new TemplateReconcilingStrategy(templateEditor, new Reloader(templateEditor))
14 |
15 | private class Reloader(templateEditor: AbstractTemplateEditor) extends IDocumentListener {
16 | def documentChanged(event: DocumentEvent) {
17 | templateEditor.compilationUnitProvider.fromEditor(templateEditor).scheduleReconcile(event.getText.toCharArray)
18 | }
19 |
20 | def documentAboutToBeChanged(event: DocumentEvent) {}
21 | }
22 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/templateeditor/sse/ContentTypeIdForScala.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.templateeditor.sse
2 |
3 | object ContentTypeIdForScala {
4 | val ContentTypeID_Scala = "org.scalaide.play2.templateSource"
5 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/templateeditor/sse/TemplateActionContributor.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.templateeditor.sse
2 |
3 | import org.eclipse.wst.html.ui.internal.edit.ui.ActionContributorHTML
4 |
5 | class TemplateActionContributor extends ActionContributorHTML {
6 | // Add refactoring actions ("RetargetTextEditorAction") here if needed
7 |
8 | override protected def getExtensionIDs(): Array[String] =
9 | Array(ContentTypeIdForScala.ContentTypeID_Scala, "org.eclipse.wst.sse.ui.StructuredTextEditor")
10 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/templateeditor/sse/TemplateContentDescriber.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.templateeditor.sse
2 |
3 | import java.io.BufferedReader
4 | import java.io.InputStreamReader
5 |
6 | import scala.annotation.tailrec
7 |
8 | import org.eclipse.core.runtime.content.IContentDescriber
9 | import org.eclipse.core.runtime.content.IContentDescription
10 |
11 | /**
12 | * Detect a Play template file if it starts with `@(` or `@*`.
13 | */
14 | class TemplateContentDescriber extends IContentDescriber {
15 |
16 | override def describe(contents: java.io.InputStream, description: IContentDescription) = {
17 |
18 | import IContentDescriber._
19 |
20 | @tailrec
21 | def checkFirstNonEmptyLine(reader: BufferedReader): Int = {
22 | val line = reader.readLine()
23 | if (line == null)
24 | INDETERMINATE
25 | else {
26 | val trimmedLine = line.trim
27 | trimmedLine.length() match {
28 | case 0 =>
29 | checkFirstNonEmptyLine(reader)
30 | case 1 =>
31 | INVALID
32 | case _ =>
33 | val c0 = trimmedLine.charAt(0)
34 | val c1 = trimmedLine.charAt(1)
35 | if (c0 == '@' && (c1 == '*' || c1 == '('))
36 | IContentDescriber.VALID
37 | else
38 | IContentDescriber.INVALID
39 | }
40 | }
41 | }
42 |
43 | checkFirstNonEmptyLine(new BufferedReader(new InputStreamReader(contents, "UTF-8")))
44 | }
45 |
46 | override def getSupportedOptions() = Array()
47 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/templateeditor/sse/hyperlink/StructuredTemplateDeclarationHyperlinkDetector.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.templateeditor.sse.hyperlink
2 |
3 | import org.eclipse.jface.text.IRegion
4 | import org.eclipse.jface.text.ITextViewer
5 | import org.eclipse.jface.text.hyperlink.AbstractHyperlinkDetector
6 | import org.eclipse.jface.text.hyperlink.IHyperlink
7 | import org.scalaide.play2.templateeditor.hyperlink.TemplateDeclarationHyperlinkDetector
8 | import org.scalaide.play2.util.StoredEditorUtils
9 |
10 |
11 | class StructuredTemplateDeclarationHyperlinkDetector extends AbstractHyperlinkDetector {
12 |
13 | /** We create a new detector every time because we need to set the context (the corresponding editor) only once.
14 | * (setContext throws an exception if it's called more than once). We could force a way to initialize this only
15 | * once at the expense of additional state in this class, but seems overkill.
16 | *
17 | * Since the detector is a lightweight class (only one field), we take this approach.
18 | */
19 | private def templateDeclHyperlinkDetector() = TemplateDeclarationHyperlinkDetector()
20 |
21 | final override def detectHyperlinks(viewer: ITextViewer, currentSelection: IRegion, canShowMultipleHyperlinks: Boolean): Array[IHyperlink] = {
22 | // make sure the context is correct
23 | val detector = templateDeclHyperlinkDetector
24 | StoredEditorUtils.getEditorOfViewer(viewer: ITextViewer).map(detector.setContext)
25 | detector.detectHyperlinks(viewer, currentSelection, canShowMultipleHyperlinks)
26 | }
27 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/templateeditor/sse/lexical/TemplateStructuredTextPartitioner.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.templateeditor.sse.lexical
2 |
3 | import org.eclipse.jface.text.DocumentEvent
4 | import org.eclipse.jface.text.IDocument
5 | import org.eclipse.jface.text.IDocumentPartitioner
6 | import org.eclipse.wst.html.core.internal.text.StructuredTextPartitionerForHTML
7 | import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion
8 | import org.eclipse.wst.sse.core.internal.text.rules.StructuredTextPartitioner
9 | import org.scalaide.play2.templateeditor.TemplateSyntaxClasses
10 | import org.scalaide.play2.templateeditor.lexical.TemplateDocumentPartitioner
11 | import org.scalaide.play2.templateeditor.lexical.TemplatePartitions
12 | import org.eclipse.jface.text.IDocumentPartitionerExtension2
13 | import org.eclipse.jface.text.ITypedRegion
14 |
15 | class TemplateStructuredTextPartitioner extends StructuredTextPartitioner with IDocumentPartitionerExtension2 {
16 |
17 | private val htmlPartitioner: StructuredTextPartitionerForHTML = new StructuredTextPartitionerForHTML
18 |
19 | override def connect(document: IDocument) = {
20 | super.connect(document)
21 | htmlPartitioner.connect(document)
22 | }
23 |
24 | override def disconnect() = {
25 | super.disconnect()
26 | htmlPartitioner.disconnect()
27 | }
28 |
29 | override def documentChanged(event: DocumentEvent): Boolean = {
30 | super.documentChanged(event)
31 | }
32 |
33 | override def computePartitioning(offset: Int, length: Int) = {
34 | htmlPartitioner.computePartitioning(offset, length)
35 | super.computePartitioning(offset, length)
36 | }
37 |
38 | override def getDefaultPartitionType() = {
39 | TemplatePartitions.TEMPLATE_DEFAULT
40 | }
41 |
42 | override def getPartitionType(region: ITextRegion, offset: Int) = {
43 | region match {
44 | case scalaRegion: TemplateTextRegion => scalaRegion.syntaxClass match {
45 | case TemplateSyntaxClasses.COMMENT => TemplatePartitions.TEMPLATE_COMMENT
46 | case TemplateSyntaxClasses.MAGIC_AT => TemplatePartitions.TEMPLATE_PLAIN
47 | case TemplateSyntaxClasses.BRACE => TemplatePartitions.TEMPLATE_PLAIN
48 | case _ => TemplatePartitions.TEMPLATE_SCALA
49 | }
50 | case _ => htmlPartitioner.getPartitionType(region, offset)
51 | }
52 | }
53 |
54 | override protected def setInternalPartition(offset: Int, length: Int, tpe: String) = {
55 | val region = htmlPartitioner.createPartition(offset, length, tpe)
56 | super.setInternalPartition(region.getOffset, region.getLength, region.getType)
57 | }
58 |
59 | override def newInstance(): IDocumentPartitioner = {
60 | val instance = new TemplateStructuredTextPartitioner
61 | instance.connect(fStructuredDocument)
62 | instance
63 | }
64 |
65 | /* IDocumentPartitionerExtension2 methods */
66 |
67 | override def getManagingPositionCategories(): Array[String] = null
68 |
69 | override def getContentType(offset: Int, preferOpenPartitions: Boolean): String =
70 | getPartition(offset, preferOpenPartitions).getType()
71 |
72 | override def computePartitioning(offset: Int, length: Int, includeZeroLengthPartitions: Boolean): Array[ITypedRegion] =
73 | computePartitioning(offset, length)
74 |
75 | override def getPartition(offset: Int, preferOpenPartitions: Boolean): ITypedRegion = {
76 | val partition = getPartition(offset)
77 | if (preferOpenPartitions && partition.getOffset() == offset && offset > 0) {
78 | getPartition(offset - 1)
79 | }
80 | else partition
81 | }
82 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/templateeditor/sse/lexical/TemplateTextRegion.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.templateeditor.sse.lexical
2 |
3 | import org.scalaide.ui.syntax.ScalaSyntaxClass
4 | import org.eclipse.wst.sse.core.internal.parser.ContextRegion
5 |
6 | case class TemplateTextRegion(syntaxClass: ScalaSyntaxClass, newStart: Int, newTextLength: Int, newLength: Int)
7 | extends ContextRegion(syntaxClass.displayName, newStart, newTextLength, newLength)
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/templateeditor/sse/model/TemplateAdapterFactoryProvider.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.templateeditor.sse.model
2 |
3 | import org.eclipse.wst.html.ui.internal.contentoutline.JFaceNodeAdapterFactoryForHTML
4 | import org.eclipse.wst.jsdt.web.core.javascript.JsTranslationAdapterFactory
5 | import org.eclipse.wst.sse.core.internal.ltk.modelhandler.IDocumentTypeHandler
6 | import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel
7 | import org.eclipse.wst.sse.ui.internal.contentoutline.IJFaceNodeAdapter
8 | import org.eclipse.wst.sse.ui.internal.provisional.registry.AdapterFactoryProvider
9 | import org.eclipse.wst.sse.ui.internal.util.Assert
10 |
11 | class TemplateAdapterFactoryProvider extends AdapterFactoryProvider {
12 |
13 | override def addAdapterFactories(structuredModel: IStructuredModel) = {
14 | val factoryRegistry = structuredModel.getFactoryRegistry()
15 | Assert.isNotNull(factoryRegistry, "Program error: client caller must ensure model has factory registry")
16 | if (factoryRegistry.getFactoryFor(classOf[IJFaceNodeAdapter]) == null) {
17 | factoryRegistry.addFactory(new JFaceNodeAdapterFactoryForHTML)
18 | }
19 | if (factoryRegistry.getFactoryFor(classOf[org.eclipse.wst.jsdt.web.core.javascript.IJsTranslation]) == null) {
20 | factoryRegistry.addFactory(new JsTranslationAdapterFactory)
21 | }
22 | }
23 |
24 | override def isFor(contentTypeDescription: IDocumentTypeHandler) = contentTypeDescription match {
25 | case _: TemplateModelHandler => true
26 | case _ => false
27 | }
28 |
29 | override def reinitializeFactories(structuredModel: IStructuredModel) = { }
30 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/templateeditor/sse/model/TemplateDocumentLoader.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.templateeditor.sse.model
2 |
3 | import org.eclipse.wst.html.core.internal.encoding.HTMLDocumentLoader
4 | import org.eclipse.wst.sse.core.internal.ltk.parser.RegionParser
5 | import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion
6 | import org.eclipse.wst.sse.core.internal.text.BasicStructuredDocument
7 | import org.eclipse.wst.xml.core.internal.parser.XMLStructuredDocumentReParser
8 | import org.scalaide.play2.templateeditor.processing.TemplateVersionExhibitor
9 | import org.scalaide.play2.templateeditor.sse.lexical.TemplateRegionParser
10 | import org.scalaide.play2.templateeditor.sse.lexical.TemplateStructuredTextPartitioner
11 |
12 | class TemplateDocumentLoader extends HTMLDocumentLoader {
13 |
14 | override def newEncodedDocument() = {
15 | val structuredDocument = TemplateStructuredDocument(getParser(), TemplateVersionExhibitor.get)
16 |
17 | // A reparser that always reparses the whole document
18 | val reparser = new XMLStructuredDocumentReParser {
19 | override protected def findDirtyEnd(end: Int): IStructuredDocumentRegion = {
20 | val result = fStructuredDocument.getLastStructuredDocumentRegion()
21 | if (result != null) fStructuredDocument.setCachedDocumentRegion(result)
22 | dirtyEnd = result
23 | dirtyEnd
24 | }
25 |
26 | override protected def findDirtyStart(start: Int): Unit = {
27 | val result = fStructuredDocument.getFirstStructuredDocumentRegion()
28 | if (result != null) fStructuredDocument.setCachedDocumentRegion(result)
29 | dirtyStart = result
30 | }
31 | }
32 |
33 | structuredDocument.delegate.setReParser(reparser)
34 |
35 | // TODO - set the default embedded type content type handler.. whatever that means.
36 | // I don't believe we'll ever need to do that, but if it comes up in the future, this is the place to do it.
37 | structuredDocument
38 | }
39 |
40 | override def newInstance() = new TemplateDocumentLoader
41 |
42 | override def getParser(): RegionParser = new TemplateRegionParser
43 |
44 | override val getDefaultDocumentPartitioner = new TemplateStructuredTextPartitioner
45 | }
46 |
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/templateeditor/sse/model/TemplateModelHandler.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.templateeditor.sse.model
2 |
3 | import org.eclipse.wst.html.core.internal.encoding.HTMLDocumentCharsetDetector
4 | import org.eclipse.wst.sse.core.internal.document.IDocumentCharsetDetector
5 | import org.eclipse.wst.sse.core.internal.document.IDocumentLoader
6 | import org.eclipse.wst.sse.core.internal.ltk.modelhandler.AbstractModelHandler
7 | import org.eclipse.wst.sse.core.internal.provisional.IModelLoader
8 |
9 | object TemplateModelHandler {
10 | val AssociatedContentTypeID = "org.scalaide.play2.templateSource"
11 | val ModelHandlerID = "org.scalaide.play2.templateModelHandler"
12 | }
13 |
14 | class TemplateModelHandler extends AbstractModelHandler() {
15 | setId(TemplateModelHandler.ModelHandlerID)
16 | setAssociatedContentTypeId(TemplateModelHandler.AssociatedContentTypeID)
17 |
18 | // Perhaps at some point it would be beneficial to have our own documentcharsetdetector.
19 | // At the moment, I don't when there would be a difference between html and template files.
20 | override def getEncodingDetector(): IDocumentCharsetDetector = new HTMLDocumentCharsetDetector
21 | override def getDocumentLoader(): IDocumentLoader = new TemplateDocumentLoader
22 | override def getModelLoader(): IModelLoader = new TemplateModelLoader
23 | }
24 |
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/templateeditor/sse/model/TemplateStructuredModel.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.templateeditor.sse.model
2 |
3 | import org.eclipse.wst.html.core.internal.document.DOMStyleModelImpl
4 | import org.eclipse.wst.html.core.internal.encoding.HTMLModelLoader
5 | import org.eclipse.wst.sse.core.internal.document.IDocumentLoader
6 | import org.eclipse.wst.sse.core.internal.provisional.IModelLoader
7 | import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel
8 |
9 | // This class (and the inner classes) will need to be overhauled when adding HTMLValidator support
10 | class TemplateStructuredModel extends DOMStyleModelImpl {
11 | import org.eclipse.wst.xml.core.internal.document.DOMModelImpl
12 | import org.eclipse.wst.xml.core.internal.document.XMLModelParser
13 | import org.eclipse.wst.xml.core.internal.document.XMLModelUpdater
14 |
15 | class NestedDOMModelParser(model: DOMModelImpl) extends XMLModelParser(model)
16 | class NestedDOMModelUpdater(model: DOMModelImpl) extends XMLModelUpdater(model)
17 | override def createModelParser() = new NestedDOMModelParser(this)
18 | override def createModelUpdater() = new NestedDOMModelUpdater(this)
19 | }
20 |
21 | class TemplateModelLoader extends HTMLModelLoader {
22 | override def getDocumentLoader(): IDocumentLoader = new TemplateDocumentLoader
23 | override def newModel(): IStructuredModel = new TemplateStructuredModel
24 | override def newInstance(): IModelLoader = new TemplateModelLoader
25 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/templateeditor/sse/style/ScalaLineStyleProvider.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.templateeditor.sse.style
2 |
3 | import org.eclipse.jface.preference.IPreferenceStore
4 | import org.eclipse.wst.html.ui.internal.style.LineStyleProviderForHTML
5 | import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion
6 | import org.eclipse.wst.sse.ui.internal.provisional.style.LineStyleProvider
7 | import org.scalaide.play2.templateeditor.sse.lexical.TemplateTextRegion
8 |
9 | class ScalaLineStyleProvider(prefStore: IPreferenceStore) extends LineStyleProviderForHTML with LineStyleProvider {
10 |
11 | protected override def getAttributeFor(region: ITextRegion) = {
12 | region match {
13 | case scalaRegion: TemplateTextRegion => {
14 | scalaRegion.syntaxClass.getTextAttribute(getColorPreferences)
15 | }
16 | case _ => super.getAttributeFor(region)
17 | }
18 | }
19 |
20 | protected override def getColorPreferences() = prefStore
21 | }
22 |
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/templateeditor/sse/validation/ScalaSourceValidator.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.templateeditor.sse.validation
2 |
3 | import scala.util.Try
4 | import org.eclipse.core.resources.IMarker
5 | import org.eclipse.core.resources.IResource
6 | import org.eclipse.core.resources.ResourcesPlugin
7 | import org.eclipse.core.runtime.Path
8 | import org.eclipse.jdt.core.IJavaModelMarker
9 | import org.eclipse.wst.sse.core.StructuredModelManager
10 | import org.eclipse.wst.validation.internal.provisional.core.IReporter
11 | import org.eclipse.wst.validation.internal.provisional.core.IValidationContext
12 | import org.eclipse.wst.validation.internal.provisional.core.IValidator
13 | import org.scalaide.play2.templateeditor.TemplateCompilationUnitProvider
14 |
15 |
16 | class ScalaSourceValidator extends IValidator {
17 |
18 | /* IValidator methods */
19 |
20 | def cleanup(report: IReporter) = {}
21 |
22 | def validate(helper: IValidationContext, reporter: IReporter) = {
23 |
24 | val wsroot = ResourcesPlugin.getWorkspace().getRoot()
25 | for {
26 | uri <- helper.getURIs()
27 | if !reporter.isCancelled()
28 | currentFile <- Option(wsroot.getFile(new Path(uri)))
29 | if currentFile.exists()
30 | model <- Try(StructuredModelManager.getModelManager().getModelForRead(currentFile))
31 | }{
32 | try {
33 | val markerType = IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER
34 | for {
35 | markers <- Try(currentFile.findMarkers(markerType, true, IResource.DEPTH_ONE))
36 | marker <- markers
37 | } marker.delete()
38 |
39 | val doc = model.getStructuredDocument()
40 | val compilationUnit = new TemplateCompilationUnitProvider(false).fromFileAndDocument(currentFile, doc)
41 | for (error <- compilationUnit.forceReconcile()) {
42 | val (priority, severity) =
43 | if (error.isError()) (IMarker.PRIORITY_HIGH, IMarker.SEVERITY_ERROR)
44 | else if (error.isWarning()) (IMarker.PRIORITY_NORMAL, IMarker.SEVERITY_WARNING)
45 | else (IMarker.PRIORITY_LOW, IMarker.SEVERITY_INFO)
46 |
47 | val marker = currentFile.createMarker(markerType)
48 | marker.setAttribute(IMarker.LINE_NUMBER, doc.getLineOfOffset(error.getSourceStart()) + 1)
49 | marker.setAttribute(IMarker.CHAR_START, error.getSourceStart())
50 | marker.setAttribute(IMarker.CHAR_END, error.getSourceStart() + (error.getSourceEnd() - error.getSourceStart() + 1))
51 | marker.setAttribute(IMarker.MESSAGE, error.getMessage())
52 | marker.setAttribute(IMarker.USER_EDITABLE, java.lang.Boolean.FALSE)
53 | marker.setAttribute(IMarker.PRIORITY, priority)
54 | marker.setAttribute(IMarker.SEVERITY, severity)
55 | }
56 | }
57 | finally {
58 | model.releaseFromRead()
59 | }
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/util/Debugger.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.util
2 |
3 | import javax.swing.JFrame
4 |
5 | object Debugger {
6 | def show(message: String) {
7 | new JFrame(message){
8 | setVisible(true)
9 | setSize(800, 100)
10 | }
11 | }
12 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/util/Images.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.util
2 |
3 | import org.scalaide.play2.PlayPlugin
4 | import org.eclipse.jface.resource.ImageDescriptor
5 |
6 | object Images {
7 | final val ROUTES_ICON = "routes.icon"
8 | final val HTTP_METHODS_ICON = "web.icon"
9 | final val URL_ICON = "url.icon"
10 | val ROUTES_ICON_DESCRIPTOR: ImageDescriptor = PlayPlugin.getImageDescriptor("icons/routes.png")
11 | val HTTP_METHODS_ICON_DESCRIPTOR: ImageDescriptor = PlayPlugin.getImageDescriptor("icons/web.png")
12 | val URL_ICON_DESCRIPTOR: ImageDescriptor = PlayPlugin.getImageDescriptor("icons/pin.png")
13 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/util/Play2PropertyTester.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.util
2 |
3 | import org.eclipse.core.expressions.PropertyTester
4 | import org.eclipse.core.resources.IProject
5 | import org.scalaide.play2.PlayPlugin
6 | import org.eclipse.jdt.core.IJavaProject
7 |
8 | object Play2PropertyTester {
9 | final val IsPlayProject = "isPlay2Project"
10 | }
11 |
12 | /** Eclipse property tester. Can check if a project is a play2 project.
13 | */
14 | class Play2PropertyTester() extends PropertyTester {
15 |
16 | // from IPropertyTester
17 |
18 | override def test(receiver: Any, property: String, args: Array[Object], expectedValue: Any): Boolean = {
19 | import Play2PropertyTester._
20 |
21 | property match {
22 | case IsPlayProject =>
23 | receiver match {
24 | case project: IProject =>
25 | PlayPlugin.instance().asPlayProject(project).isDefined
26 | case project: IJavaProject =>
27 | PlayPlugin.instance().asPlayProject(project.getProject()).isDefined
28 | case _ =>
29 | false
30 | }
31 | case _ =>
32 | false
33 | }
34 | }
35 |
36 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/util/StoredEditorUtils.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.util
2 |
3 | import org.eclipse.jface.text.TextViewer
4 | import org.scalaide.play2.templateeditor.AbstractTemplateEditor
5 | import org.eclipse.jface.text.ITextViewer
6 | import org.eclipse.core.resources.IFile
7 | import org.eclipse.ui.IFileEditorInput
8 | import org.eclipse.jface.text.source.ISourceViewer
9 |
10 | object StoredEditorUtils {
11 |
12 | def getFileOfViewer(viewer: ITextViewer): Option[IFile] = {
13 | getEditorOfViewer(viewer).map(_.getEditorInput).collect{
14 | case fileEditorInput: IFileEditorInput =>
15 | fileEditorInput.getFile
16 | }
17 | }
18 |
19 | def getEditorOfViewer(viewer: ITextViewer): Option[AbstractTemplateEditor] =
20 | viewer match {
21 | case textViewer: TextViewer =>
22 | Option(textViewer.getData("scalaide.play.editor").asInstanceOf[AbstractTemplateEditor])
23 | case _ =>
24 | None
25 | }
26 |
27 | def storeEditorInViewer(sourceViewer: ISourceViewer, editor: AbstractTemplateEditor) {
28 | sourceViewer match {
29 | case tv: TextViewer =>
30 | tv.setData("scalaide.play.editor", editor)
31 | case _ =>
32 | }
33 | }
34 |
35 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/util/SyncedScopedPreferenceStore.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.util
2 |
3 | import org.eclipse.core.resources.IProject
4 | import org.eclipse.core.resources.ProjectScope
5 | import org.eclipse.ui.preferences.ScopedPreferenceStore
6 |
7 | class SyncedScopedPreferenceStore(project: IProject, pluginId: String) {
8 |
9 | private val preferenceStore = new ScopedPreferenceStore(new ProjectScope(project), pluginId)
10 |
11 | def getString(name: String): String = {
12 | preferenceStore.synchronized {
13 | preferenceStore.getString(name)
14 | }
15 | }
16 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/wizards/NewTemplateWizard.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.wizards
2 |
3 | import org.eclipse.jface.viewers.IStructuredSelection
4 | import org.eclipse.jface.wizard.Wizard
5 | import org.eclipse.ui.INewWizard
6 | import org.eclipse.ui.IWorkbench
7 | import org.eclipse.ui.PartInitException
8 | import org.eclipse.ui.PlatformUI
9 | import org.eclipse.ui.ide.IDE
10 | import org.scalaide.logging.HasLogger
11 | import org.scalaide.util.ui.DisplayThread
12 |
13 | /**
14 | * A wizard to create a new Play template file.
15 | */
16 | class NewTemplateWizard extends Wizard with INewWizard with HasLogger {
17 |
18 | // from org.eclipse.jface.wizard.Wizard
19 |
20 | override def performFinish(): Boolean = {
21 | val file = newFileWizardPage.createNewFile()
22 |
23 | if (file != null) {
24 | // if it worked, open the file
25 | DisplayThread.asyncExec {
26 | val page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage()
27 | try {
28 | IDE.openEditor(page, file, true)
29 | } catch {
30 | case e: PartInitException => eclipseLog.error("Failed to initialize editor for file "+ file.getName())
31 | }
32 | }
33 | true
34 | } else {
35 | false
36 | }
37 | }
38 |
39 | override def addPages() {
40 | newFileWizardPage = new NewTemplateWizardPage(selection)
41 | addPage(newFileWizardPage)
42 | }
43 |
44 | // from org.eclipse.ui.INewWizard
45 |
46 | override def init(workbench: IWorkbench, selection: IStructuredSelection) {
47 | this.selection = selection
48 | }
49 |
50 | // ------
51 |
52 | // set the dialog values
53 | setWindowTitle("New Play Template")
54 |
55 | /**
56 | * The wizard page
57 | */
58 | private var newFileWizardPage: NewTemplateWizardPage = _
59 |
60 | /**
61 | * The selection at the initialization of the wizard
62 | */
63 | private var selection: IStructuredSelection = _
64 |
65 | }
--------------------------------------------------------------------------------
/org.scala-ide.play2/src/org/scalaide/play2/wizards/NewTemplateWizardPage.scala:
--------------------------------------------------------------------------------
1 | package org.scalaide.play2.wizards
2 |
3 | import java.io.ByteArrayInputStream
4 | import java.io.InputStream
5 | import org.eclipse.core.runtime.IStatus
6 | import org.eclipse.core.runtime.Status
7 | import org.eclipse.jface.viewers.IStructuredSelection
8 | import org.eclipse.swt.widgets.Composite
9 | import org.eclipse.ui.dialogs.WizardNewFileCreationPage
10 | import org.scalaide.play2.PlayPlugin
11 |
12 | /**
13 | * Wizard page based of the new file creation page from the framework.
14 | * The advanced section has be removed.
15 | */
16 | class NewTemplateWizardPage(selection: IStructuredSelection) extends WizardNewFileCreationPage("main", selection) {
17 |
18 | // from org.eclipse.ui.dialogs.WizardNewFileCreationPage
19 |
20 | override def createAdvancedControls(parent: Composite) {
21 | // do nothing, we don't want the 'advanced' section
22 | }
23 |
24 | override def createLinkTarget() {
25 | // do nothing, we don't have this section
26 | }
27 |
28 | override def getInitialContents(): InputStream = {
29 | new ByteArrayInputStream(
30 | """@* %s Template File *@
31 | @(param: Any)
32 | """
33 | .format(objectName).getBytes())
34 | }
35 |
36 | override def validateLinkedResource(): IStatus = {
37 | // do nothing, we don't have this section
38 | Status.OK_STATUS
39 | }
40 |
41 | override def validatePage(): Boolean = {
42 | if (super.validatePage()) {
43 | if (validateIdentifier) {
44 | true
45 | } else {
46 | setErrorMessage("Invalid template name")
47 | false
48 | }
49 | } else {
50 | false
51 | }
52 | }
53 |
54 | // ------
55 |
56 | // set the page values
57 | setTitle("Play Template")
58 | setDescription("Create a new Play Template")
59 | setFileExtension(PlayPlugin.TemplateExtension)
60 |
61 | /**
62 | * Return the name of the object to be created, or empty if not available.
63 | */
64 | def objectName = {
65 | val fileName = getFileName()
66 | val extenstionLength = ("." + PlayPlugin.TemplateExtension).length()
67 | if (fileName.length > extenstionLength) {
68 | fileName.substring(0, fileName.length() - extenstionLength)
69 | } else {
70 | ""
71 | }
72 | }
73 |
74 | /**
75 | * check if the object name is a valid identifier.
76 | * TODO: switch to Scala identifier check. Right now it is checking for a Java identifier
77 | */
78 | def validateIdentifier: Boolean = {
79 | objectName.toList match {
80 | case Nil =>
81 | true
82 | case head :: Nil =>
83 | Character.isJavaIdentifierStart(head)
84 | case head :: tail =>
85 | Character.isJavaIdentifierStart(head) && tail.foldLeft(true)((b: Boolean, c: Char) => b && Character.isJavaIdentifierPart(c))
86 | }
87 | }
88 |
89 | }
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | 3.0
7 |
8 |
9 |
10 | org.scala-ide
11 | plugin-profiles
12 | 1.0.14
13 |
14 |
15 | org.scala-ide
16 | org.scala-ide.play2.build
17 | 0.11.0-SNAPSHOT
18 | Play 2 Support for Scala IDE
19 | pom
20 |
21 |
22 | org.scala-ide.play2
23 | org.scala-ide.play2.templates
24 | org.scala-ide.play2.tests
25 | org.scala-ide.play2.feature
26 | org.scala-ide.play2.source.feature
27 | org.scala-ide.play2.update-site
28 |
29 |
30 |
31 | 2.12
32 |
33 | twirl-compiler_${scala.binary.version}
34 | 1.2.0.v20160929-1449
35 | twirl-parser_${scala.binary.version}
36 | 1.3.0
37 |
38 |
39 |
40 |
41 |
42 | com.typesafe.play
43 | ${twirl-compiler.artifactId}
44 | ${twirl.version}
45 |
46 |
47 | com.typesafe.play
48 | ${twirl-parser.artifactId}
49 | ${twirl.version}
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------