Skip to content

Commit 1bd02ea

Browse files
support functions, procedures, types in the parser
1 parent f48e6b4 commit 1bd02ea

File tree

3 files changed

+132
-46
lines changed

3 files changed

+132
-46
lines changed

sqldev/src/main/java/org/utplsql/sqldev/model/parser/PlsqlObject.xtend

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import org.utplsql.sqldev.model.ut.Annotation
2323
@Accessors
2424
class PlsqlObject extends AbstractModel {
2525
String name
26+
String type
2627
Integer position
2728
List<Annotation> annotations
2829
}

sqldev/src/main/java/org/utplsql/sqldev/parser/UtplsqlParser.xtend

Lines changed: 34 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -93,10 +93,11 @@ class UtplsqlParser {
9393
}
9494

9595
private def populateObjects() {
96-
val p = Pattern.compile("(?i)(\\s*)(create(\\s+or\\s+replace)?\\s+(package)\\s+(body\\s+)?)([^\\s]+)(\\s+)")
96+
val p = Pattern.compile("(?i)(\\s*)(create(\\s+or\\s+replace)?\\s+(package|type|function|procedure)\\s+(body\\s+)?)([^\\s]+)(\\s+)")
9797
val m = p.matcher(plsqlReduced)
9898
while (m.find) {
9999
val o = new PlsqlObject
100+
o.type = m.group(4).toUpperCase
100101
o.name = m.group(6)
101102
o.position = m.start
102103
objects.add(o)
@@ -145,22 +146,44 @@ class UtplsqlParser {
145146
}
146147
}
147148
}
148-
149-
private def getObjectAt(int position) {
149+
150+
/**
151+
* gets the PL/SQL object based on the current editor position
152+
*
153+
* @param position the absolute position as used in {@link JTextComponent#getCaretPosition()}
154+
* @return the PL/SQL object
155+
*/
156+
def getObjectAt(int position) {
150157
var PlsqlObject obj
151158
for (o : objects) {
152159
if (o.position <= position) {
153160
obj = o
154161
}
155162
}
156163
return obj
157-
}
158-
159-
private def getObjectNameAt(int position) {
160-
val o = getObjectAt(position)
161-
return if (o !== null) {o.name} else {""}
162164
}
163165

166+
/**
167+
* converts a line and column to a postion as used in as used in {@link JTextComponent#getCaretPosition()}
168+
* used for testing purposes only
169+
*
170+
* @param line the line as used in SQL Developer, starting with 1
171+
* @param column the column as used in SQL Developer, starting with 1
172+
* @return the position
173+
*/
174+
def toPosition(int line, int column) {
175+
var lines=0
176+
for (var i=0; i<plsql.length; i++) {
177+
if (plsql.substring(i,i+1) == "\n") {
178+
lines++
179+
if (lines == line - 1) {
180+
return (i + column)
181+
}
182+
}
183+
}
184+
throw new RuntimeException('''Line «line» not found.''')
185+
}
186+
164187
private def getUnitNameAt(int position) {
165188
var name = ""
166189
for (u : units) {
@@ -190,33 +213,13 @@ class UtplsqlParser {
190213
* @return the utPLSQL path
191214
*/
192215
def getPathAt(int position) {
193-
var objectName = getObjectNameAt(position)
194-
if (!objectName.empty) {
216+
var object = getObjectAt(position)
217+
if (object !== null && object.type == "PACKAGE") {
195218
var unitName = getUnitNameAt(position)
196-
val path = '''«IF owner !== null»«owner».«ENDIF»«objectName.fixName»«IF !unitName.empty».«unitName.fixName»«ENDIF»'''
219+
val path = '''«IF owner !== null»«owner».«ENDIF»«object.name.fixName»«IF !unitName.empty».«unitName.fixName»«ENDIF»'''
197220
return path
198221
}
199222
return ""
200223
}
201-
202-
/**
203-
* gets the utPLSQL path based on the current editor position
204-
*
205-
* @param line the line as used in SQL Developer, starting with 1
206-
* @param column the column as used in SQL Developer, starting with 1
207-
* @return the utPLSQL path
208-
*/
209-
def getPathAt(int line, int column) {
210-
var lines=0
211-
for (var i=0; i<plsql.length; i++) {
212-
if (plsql.substring(i,i+1) == "\n") {
213-
lines++
214-
if (lines == line - 1) {
215-
return getPathAt(i + column)
216-
}
217-
}
218-
}
219-
throw new RuntimeException('''Line «line» not found.''')
220-
}
221224

222225
}

sqldev/src/test/java/org/utplsql/sqldev/tests/UtplsqlParserTest.xtend

Lines changed: 97 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -86,14 +86,14 @@ class UtplsqlParserTest extends AbstractJdbcTest {
8686
Assert.assertEquals('''"P"'''.toString, units.get(1).name)
8787
Assert.assertTrue(units.get(0).position < units.get(1).position)
8888
Assert.assertEquals("", parser.getPathAt(0))
89-
Assert.assertEquals("", parser.getPathAt(3,6))
90-
Assert.assertEquals("pkg", parser.getPathAt(4,1))
91-
Assert.assertEquals("pkg.p", parser.getPathAt(10,33))
92-
Assert.assertEquals("pkg.p", parser.getPathAt(13,1))
93-
Assert.assertEquals("SCOTT.PKG.P", parser.getPathAt(19,1))
94-
Assert.assertEquals("SCOTT.PKG.P", parser.getPathAt(22,9))
95-
Assert.assertEquals("SCOTT.PKG.P", parser.getPathAt(22,10))
96-
Assert.assertEquals("SCOTT.PKG.P", parser.getPathAt(29,1))
89+
Assert.assertEquals("", parser.getPathAt(parser.toPosition(3,6)))
90+
Assert.assertEquals("pkg", parser.getPathAt(parser.toPosition(4,1)))
91+
Assert.assertEquals("pkg.p", parser.getPathAt(parser.toPosition(10,33)))
92+
Assert.assertEquals("pkg.p", parser.getPathAt(parser.toPosition(13,1)))
93+
Assert.assertEquals("SCOTT.PKG.P", parser.getPathAt(parser.toPosition(19,1)))
94+
Assert.assertEquals("SCOTT.PKG.P", parser.getPathAt(parser.toPosition(22,9)))
95+
Assert.assertEquals("SCOTT.PKG.P", parser.getPathAt(parser.toPosition(22,10)))
96+
Assert.assertEquals("SCOTT.PKG.P", parser.getPathAt(parser.toPosition(29,1)))
9797
}
9898

9999
@Test
@@ -124,8 +124,8 @@ class UtplsqlParserTest extends AbstractJdbcTest {
124124
parser = new UtplsqlParser(sqlScript, dataSource.connection, null)
125125
Assert.assertEquals(2, parser.getObjects.size)
126126
Assert.assertEquals(2, parser.getUnits.size)
127-
Assert.assertEquals("pkg.p", parser.getPathAt(13,1))
128-
Assert.assertEquals("SCOTT.PKG.P", parser.getPathAt(19,1))
127+
Assert.assertEquals("pkg.p", parser.getPathAt(parser.toPosition(13,1)))
128+
Assert.assertEquals("SCOTT.PKG.P", parser.getPathAt(parser.toPosition(19,1)))
129129
setupAndTeardown
130130
}
131131

@@ -178,12 +178,12 @@ class UtplsqlParserTest extends AbstractJdbcTest {
178178
end;
179179
'''
180180
val parser = new UtplsqlParser(plsql)
181-
Assert.assertEquals("test_expect_not_to_be_null.cleanup_expectations", parser.getPathAt(7,1))
182-
Assert.assertEquals("test_expect_not_to_be_null.create_types", parser.getPathAt(13,1))
181+
Assert.assertEquals("test_expect_not_to_be_null.cleanup_expectations", parser.getPathAt(parser.toPosition(7,1)))
182+
Assert.assertEquals("test_expect_not_to_be_null.create_types", parser.getPathAt(parser.toPosition(13,1)))
183183
// was: '||gc_varray_name||'.drop_types
184-
Assert.assertEquals("test_expect_not_to_be_null.drop_types", parser.getPathAt(23,1))
184+
Assert.assertEquals("test_expect_not_to_be_null.drop_types", parser.getPathAt(parser.toPosition(23,1)))
185185
// was: '||gc_varray_name||'.blob_not_null
186-
Assert.assertEquals("test_expect_not_to_be_null.blob_not_null", parser.getPathAt(33,1))
186+
Assert.assertEquals("test_expect_not_to_be_null.blob_not_null", parser.getPathAt(parser.toPosition(33,1)))
187187
}
188188

189189
@Test
@@ -215,7 +215,89 @@ class UtplsqlParserTest extends AbstractJdbcTest {
215215
'''
216216
val parser = new UtplsqlParser(plsql)
217217
// was: test_expect_not_to_be_null.create_types
218-
Assert.assertEquals("test_expect_not_to_be_null.blob_not_null", parser.getPathAt(13,26))
218+
Assert.assertEquals("test_expect_not_to_be_null.blob_not_null", parser.getPathAt(parser.toPosition(13,26)))
219219
}
220220

221+
@Test
222+
def testProcedure() {
223+
val plsql = '''
224+
create or replace procedure z
225+
is
226+
null;
227+
end;
228+
/
229+
'''
230+
val parser = new UtplsqlParser(plsql)
231+
Assert.assertEquals("z", parser.getObjectAt(0).name)
232+
Assert.assertEquals("PROCEDURE", parser.getObjectAt(0).type)
233+
}
234+
235+
@Test
236+
def testFunction() {
237+
val plsql = '''
238+
create or replace procedure z
239+
is
240+
null;
241+
end;
242+
/
243+
244+
create or replace function f return number is
245+
begin
246+
null;
247+
end;
248+
/
249+
'''
250+
val parser = new UtplsqlParser(plsql)
251+
Assert.assertEquals("f", parser.getObjectAt(parser.toPosition(8,1)).name)
252+
Assert.assertEquals("FUNCTION", parser.getObjectAt(parser.toPosition(8,1)).type)
253+
}
254+
255+
@Test
256+
def testType() {
257+
val plsql = '''
258+
create or replace type t force is
259+
object (
260+
a number,
261+
b number,
262+
c varchar2(10),
263+
member procedure p(self in t)
264+
)
265+
end;
266+
/
267+
'''
268+
val parser = new UtplsqlParser(plsql)
269+
Assert.assertEquals("t", parser.getObjectAt(0).name)
270+
Assert.assertEquals("TYPE", parser.getObjectAt(0).type)
271+
}
272+
273+
@Test
274+
def testTypeBody() {
275+
val plsql = '''
276+
create or replace type body t force is
277+
member procedure p(self in t) is
278+
begin
279+
null;
280+
end;
281+
end;
282+
/
283+
'''
284+
val parser = new UtplsqlParser(plsql)
285+
Assert.assertEquals("t", parser.getObjectAt(0).name)
286+
Assert.assertEquals("TYPE", parser.getObjectAt(0).type)
287+
}
288+
289+
@Test
290+
def testUnknown() {
291+
val plsql = '''
292+
create or replace unknown u is
293+
begin
294+
null;
295+
end;
296+
/
297+
'''
298+
val parser = new UtplsqlParser(plsql)
299+
Assert.assertEquals(null, parser.getObjectAt(0))
300+
}
301+
302+
221303
}

0 commit comments

Comments
 (0)