Skip to content

Commit c78d73a

Browse files
Marcellourbani/issue191 (#219)
* small unittest fix * improved inactive object support * If i re-save or activate after the first activation of the abap source in vscode, there is no response #191
1 parent 6ca4199 commit c78d73a

File tree

18 files changed

+460
-675
lines changed

18 files changed

+460
-675
lines changed

client/package-lock.json

Lines changed: 302 additions & 112 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

client/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
"@types/uuid": "^9.0.0",
4545
"@types/vscode": "^1.74.0",
4646
"@types/vscode-windows-registry": "^1.0.0",
47-
"axios": "^0.23.0",
47+
"axios": "^1.6.8",
4848
"jest": "^29.3.1",
4949
"rimraf": "^3.0.2",
5050
"terser-webpack-plugin": "^5.3.6",
@@ -61,7 +61,7 @@
6161
"@abaplint/core": "^2.102.65",
6262
"@types/tmp": "0.2.3",
6363
"abap_cloud_platform": "^1.1.3",
64-
"abap-adt-api": "^5.2.7",
64+
"abap-adt-api": "^6.0.0",
6565
"abapfs": "file:../modules/abapfs",
6666
"abapobject": "file:../modules/abapObject",
6767
"client-oauth2": "^4.3.3",

client/src/adt/operations/AdtObjectActivator.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@ export interface ActivationEvent {
1313
}
1414

1515
export class AdtObjectActivator {
16-
constructor(private client: ADTClient) {}
16+
constructor(private client: ADTClient) { }
1717
private static instances = new Map<string, AdtObjectActivator>()
1818
private emitter = new EventEmitter<ActivationEvent>()
1919
public static get(connId: string) {
2020
let instance = this.instances.get(connId)
2121
if (!instance) {
22-
instance = new AdtObjectActivator(getClient(connId))
22+
instance = new AdtObjectActivator(getClient(connId, false))
2323
this.instances.set(connId, instance)
2424
}
2525
return instance
@@ -54,7 +54,7 @@ export class AdtObjectActivator {
5454
const { name, path } = object.lockObject
5555
let result
5656
const mainProg = await this.getMain(object, uri)
57-
result = await this.client.activate(name, path, mainProg)
57+
result = await this.client.activate(name, path, mainProg, true)
5858
if (!result.success) {
5959
let inactives
6060
if (result.inactive.length > 0)

client/src/adt/operations/UnitTestRunner.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ const runHandler = (runner: UnitTestRunner) => async (request: TestRunRequest) =
199199
if (excluded(i)) continue
200200
const classes = await runUnitUrl(connId, i.id)
201201
runner.setUrlTypes(classes)
202-
const obj = (i: TestItem): TestItem => runner.getUrlType(i.id) === TestResType.object ? i : obj(i.parent!)
202+
const obj = (i: TestItem): TestItem => runner.getUrlType(i.id) === TestResType.object || !i.parent ? i : obj(i.parent)
203203
const resType = runner.getUrlType(i.id)
204204
const actualResType = resType === TestResType.method && (classes.length > 1 || classes[0] && classes[0].testmethods.length > 1) ? TestResType.object : resType
205205
setResults(run, classes, obj(i), runner.controller, actualResType)

client/src/commands/commands.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import { createConnection } from "./connectionwizard"
3939
import { types } from "util"
4040
import { atcProvider } from "../views/abaptestcockpit"
4141
import { context } from "../extension"
42+
import { FsProvider } from "../fs/FsProvider"
4243

4344
export function currentUri() {
4445
if (!window.activeTextEditor) return
@@ -159,7 +160,7 @@ export class AdtCommands {
159160
}
160161
await activator.activate(obj, uri)
161162
if (editor === window.activeTextEditor) {
162-
await obj.loadStructure() // TODO replace with stat?
163+
await workspace.fs.stat(uri)
163164
await showHideActivate(editor)
164165
}
165166
}

client/src/lib/mongoClient.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { cache } from "./functions"
66
import { clientTraceUrl, Sources, httpTraceUrl } from "vscode-abap-remote-fs-sharedapi"
77
import { LogCallback, LogData, session_types } from "abap-adt-api"
88
import { caughtToString } from "."
9-
import { AxiosRequestHeaders } from "axios"
9+
import { AxiosRequestHeaders, RawAxiosRequestHeaders } from "axios"
1010

1111
const CALLLOG = "callLog"
1212
const HTTPLOG = "httpLog"
@@ -30,12 +30,12 @@ interface HttpRequest {
3030
stateful: boolean
3131
method: string
3232
uri: string
33-
headers: AxiosRequestHeaders
33+
headers: Record<string, string | string[] | number>
3434
requestBody: any
3535
debugId: number
3636
}
3737
interface HttpLog extends HttpRequest {
38-
responseHeaders: AxiosRequestHeaders
38+
responseHeaders: Record<string, string | string[] | number>
3939
duration: number
4040
statusCode: number
4141
// unknownResponse: boolean

client/src/scm/abapGit/documentProvider.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class GitDocProvider implements TextDocumentContentProvider {
1818
if (!key || !path || !gitScm) throw new Error(`Invalid URL`)
1919
const client = getClient(uri.authority)
2020
const { user, password } = gitScm.credentials || {}
21-
return client.getObjectSource(path.replace(/#/g, "%23"), user, password)
21+
return client.getObjectSource(path.replace(/#/g, "%23"), { gitUser: user, gitPassword: password })
2222
}
2323
}
2424

modules/abapObject/package-lock.json

Lines changed: 13 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

modules/abapObject/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,6 @@
2020
"typescript": "^4.9.4"
2121
},
2222
"dependencies": {
23-
"abap-adt-api": "^5.2.7"
23+
"abap-adt-api": "^6.0.0"
2424
}
2525
}

modules/abapObject/src/AOService.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export interface AbapObjectService {
2525
transport: string
2626
) => Promise<void>
2727
delete: (path: string, lockId: string, transport: string) => Promise<void>
28-
getObjectSource: (path: string) => Promise<string>
28+
getObjectSource: (path: string, version?: ObjectVersion) => Promise<string>
2929
nodeContents: (type: NodeParents, name: string, owner?: string) => Promise<NodeStructure>
3030
}
3131

@@ -74,8 +74,8 @@ export class AOService implements AbapObjectService {
7474
)
7575
}
7676

77-
getObjectSource(path: string) {
78-
return this.client.statelessClone.getObjectSource(path)
77+
getObjectSource(path: string, version?: ObjectVersion) {
78+
return this.client.statelessClone.getObjectSource(path, { version })
7979
}
8080

8181
private contentsCache = new Map<string, Promise<NodeStructure>>()

modules/abapObject/src/AbapObject.ts

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -53,17 +53,19 @@ export interface AbapObject {
5353
readonly canBeWritten: boolean
5454
/** objcect namespace
5555
* i.e. for /UI5/IF_ADT_REP_MODEL is /UI5/
56-
*/
56+
*/
5757
readonly nameSpace: string
5858
/** object base name
5959
* i.e. for /UI5/IF_ADT_REP_MODEL is IF_ADT_REP_MODEL
60-
*/
60+
*/
6161
readonly baseName: string
6262
/** used to open the object in SAPGUI */
6363
readonly sapGuiUri: string
6464
/** supported or only sapgui */
6565
readonly supported: boolean
6666
readonly owner?: string
67+
readonly modtime: number
68+
readonly version: ObjectVersion | undefined
6769

6870
/** loads/updates the object metadata */
6971
loadStructure: (refresh?: boolean, version?: ObjectVersion) => Promise<AbapObjectStructure>
@@ -120,6 +122,9 @@ export class AbapObjectBase implements AbapObject {
120122
public get structure(): AbapObjectStructure | undefined {
121123
return this._structure
122124
}
125+
get modtime() {
126+
return this.structure?.metaData["adtcore:changedAt"] ?? 0
127+
}
123128
public set structure(value: AbapObjectStructure | undefined) {
124129
this._structure = value
125130
}
@@ -137,6 +142,10 @@ export class AbapObjectBase implements AbapObject {
137142
get fsName() {
138143
return `${convertSlash(this.name)}${this.extension}`
139144
}
145+
get version(): ObjectVersion | undefined {
146+
const version = this.structure?.metaData["adtcore:version"]
147+
if (version === "active" || version === "inactive") return version
148+
}
140149
get lockObject(): AbapObject {
141150
return this
142151
}
@@ -183,12 +192,21 @@ export class AbapObjectBase implements AbapObject {
183192
if (this.expandable) throw ObjectErrors.notLeaf(this)
184193
return this.service.mainPrograms(this.path)
185194
}
186-
195+
private _loadstprom: Promise<AbapObjectStructure> | undefined = undefined
187196
async loadStructure(refresh = false, version?: ObjectVersion): Promise<AbapObjectStructure> {
188-
if (!this.name) throw ObjectErrors.noStructure(this)
189-
const base = this.path.replace(/\/source\/main$/, "")
190-
this.structure = await this.service.objectStructure(base, refresh, version)
191-
return this.structure
197+
if (!this._loadstprom) {
198+
const loader = async () => {
199+
if (!this.name) throw ObjectErrors.noStructure(this)
200+
const base = this.path.replace(/\/source\/main$/, "")
201+
const structure = await this.service.objectStructure(base, refresh, version)
202+
const metaData = structure.metaData
203+
if (!this.structure || metaData["adtcore:changedAt"] >= this.modtime)
204+
this.structure = structure
205+
return this.structure
206+
}
207+
this._loadstprom = loader().finally(() => this._loadstprom = undefined)
208+
}
209+
return this._loadstprom
192210
}
193211
async delete(lockId: string, transport = "") {
194212
return this.service.delete(this.path, lockId, transport)
@@ -211,9 +229,11 @@ export class AbapObjectBase implements AbapObject {
211229
}
212230

213231
async read() {
232+
await this._loadstprom
214233
if (this.expandable) throw ObjectErrors.notLeaf(this)
215234
if (!this.supported) return SAPGUIONLY
216-
return this.service.getObjectSource(this.contentsPath())
235+
const version = this.version === "inactive" ? "inactive" : undefined
236+
return this.service.getObjectSource(this.contentsPath(), version)
217237
}
218238

219239
protected filterInvalid(original: NodeStructure): NodeStructure {

modules/abapfs/package-lock.json

Lines changed: 13 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

modules/abapfs/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,6 @@
2020
"typescript": "^4.9.4"
2121
},
2222
"dependencies": {
23-
"abap-adt-api": "^5.2.7"
23+
"abap-adt-api": "^6.0.0"
2424
}
2525
}

modules/abapfs/src/abapFile.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { FileStat, FileType, FileSystemError } from "vscode"
22
import { AbapObject } from "../../abapObject"
33
import { AbapFsService } from "."
44
import { AbapFolder, isAbapFolder } from "./abapFolder"
5-
import { isCreatableTypeId } from "abap-adt-api"
5+
import { ObjectVersion, isCreatableTypeId } from "abap-adt-api"
66
const tag = Symbol("AbapFile")
77

88
interface FileCache {
@@ -17,33 +17,33 @@ export class AbapFile implements FileStat {
1717
readonly object: AbapObject,
1818
readonly parent: FileStat,
1919
private service: AbapFsService
20-
) {}
20+
) { }
2121
get ctime() {
22-
if (this.object.structure)
23-
return this.object.structure.metaData["adtcore:createdAt"]
24-
return 0
22+
return this.object.structure?.metaData["adtcore:createdAt"] ?? 0
2523
}
2624
get mtime() {
27-
if (this.object.structure)
28-
return this.object.structure.metaData["adtcore:changedAt"]
29-
return 0
25+
return this.object.modtime
3026
}
3127

32-
get version() {
33-
return this.object.structure?.metaData["adtcore:version"]
28+
get version(): ObjectVersion | undefined {
29+
return this.object.version
3430
}
3531

3632
private cache: FileCache | undefined
3733
private timer: NodeJS.Timeout | undefined
3834

3935
async stat() {
40-
if (this.object.supported) await this.object.loadStructure()
36+
if (this.object.supported) {
37+
await this.object.loadStructure()
38+
const inactive = this.object.structure?.links?.find(l => l.rel === "http://www.sap.com/adt/relations/objectstates")
39+
if (inactive) await this.object.loadStructure(true, "inactive")
40+
}
4141
}
4242

4343
size = 0
4444
async read() {
4545
if (!this.object.structure && this.object.supported)
46-
await this.object.loadStructure()
46+
await this.stat()
4747
if (this.cache?.mtime === this.mtime) return this.cache.source
4848
if (this.timer) clearTimeout(this.timer)
4949
const source = await this.object.read()

0 commit comments

Comments
 (0)